하나 이상의 추상 메소드를 포함한 클래스(abstract class)
객체를 직접 생성할 수 있는 클래스를 실체 클래스라 한다면 이 클래스들의 공통적인 특성을 추출해서 선언 한 클래스를 추상 클래스라 한다.
비슷한 인터페이스 와의 차이점은 추상 클래스는 "추상 메서드 만" 포함하나, 추상 클래스는 하나의 추상 메서드만 포함하면 추상 클래스가 된다.
여기서 말하는 추상 메서드란, 함수 선언만 되어있고 구현부가 없는 메서드를 말한다.
추상 메서드의 예
public abstract class 클래스명();
실체 클래스의 공통적인 특성(필드 , 메소드) 를 뽑아내어 추상 클래스로 만드는 이유는 무엇이 있을까...
실체 클래스를 설계하는 사람이 여러 사람일 경우, 실체 클래스마다 필드와 메소드가 제각개ㅣ 다른 이름을 가질 수 있다.
아래와 같은 상황을 예시로 들자면...
Telephone
클래스 안의 소유자는 owner
전원을 켜는 메소드가 turnOn()
SmartPhone
클래스 안의 소유자는 user
전원을 켜는 메소드가 powerOn()
위 같은 상황이라고 하면 데이터와 기능이 동일하지만 이름이 달라, 객체마다 사용 방법이 달라진다.
그래서 이같은 경우에 해결하는 방법으로는 아래와 같다.
Phone
이라는 추상 클래스에 owenr
필드와 turnOn()
메소드를 선언
Telephone
과 SmartPhone
은 이 phone
을 상속함으로써 필드와 메소드 이름을 통일한다.
위의 예시를 그대로 가져와서 설명
공통적인 필드와 메소드는 추상 클래스인Phone
에 모두 선언해두고, 다른 점만을 실체 클래스에 선언한다.
이를 통해서 실체 클래스를 작성하는데 시간을 절약할 수 있다.
위 이미지 처럼 owner
필드와 turnOn()
메소드는 선언할 필요가 없다.
추가적인 특성인 autoAnswering()
와 internetSearch()
메소드만 각각 선언하면 된다.
추상 클래스의 선언에는 클래스 선언에
abstract
키워드를 붙여주면 된다.
이렇게 하면 new 연산자를 통해서 객체를 만들지 못하고 상속을 통해 자식 클래스만 만들 수 있다.
추상 클래스도 일반 클래스와 마찬가지로 필드 , 생성자, 메소드 의 생성 및 선언이 가능하다.
객체가 생성될 때 super(...)
를 호출해서 추상 클래스 객체를 생성하므로 추상 클래스도 생성자가 반드시 있어야 한다.
아래의 예제를 통해 확인해 보았다.
추상 메소드
메소드는 () 선언부와 {} 구현부로 나누어 지는데, 선언부 까지만 작성하고 구현부는 작성하지 않은 메소드를 의미한다.\
추상 클래스 설계 시 하위 클래스가 반드시 실행 내용을 채우도록 강제하고 싶은 메소드가 있을 경우에 해당 메소드를 추상 메소드로 선언한다.
이경우 자식 클래스는 반드시 추상 메소드를 재정의해서 실행 내용을 작성해야 하는데 그렇지 않으면 컴파일 에러가 발생한다.
이번에도 마찬가지로 예제를 들어 이해해보자
첫번째 방법은 가장 일반적인 방식으로 Dog 와 Cat 변수의 호출
두번째의 경우 Animal 변수로 타입 변환해서 sound() 메소드를 호출
자식은 부모타입으로 자동 타입변환이 가능하고,
메소드가 재정의되어 있을 경우 재정의된 자식 메소드가 호출되는 다형성의 특징이 그대로 적용된다.
세번째의 경우 부모 타입의 매개 변수에 자식 객체를 대입해서 메소드의 다형성을 적용했다.
원리는 두번째와 같으며, 자식 객체가 부모 타입으로 자동 타입 변환되어 재정의된 sound() 메소드가 호출된다.
추상 클래스 : 클래스들의 공통적인 필드와 메소드를 추출해서 선언한 클래스를 의미한다.
추상 메소드 : 추상 클래스에서만 선언할 수 있고, 메소드의 선언부만 있는 메소드를 의미한다.
추상 메소드는 자식 클래스에서 재정의되어 실행 내용을 결정해야 한다.