3. 상속
상속 개념
부모 클래스의 멤버(필드, 메소드)를 자식 클래스에게 물려주는 것
상속의 장점
공통 속성을 가진 클래스를 빠르게 작성하도록 도와줌
부모 클래스 수정으로 자식 클래스의 수정 효과도 가져오기 때문에 유지보수 시간을 최소화
다형성의 적극적 이용 가능
멤버가 상속되지 않는 경우
부모 클래스에서
private
접근 제한자를 갖는 필드, 메소드는 상속 대상에서 제외된다.부모 클래스와 자식 클래스가 다른 패키지에 존재한다면,
default
접근 제한을 갖는 필드와 메소드도 상속 대상에서 제외된다.
다중 상속
기본적으로 허용 안함
인터페이스는 다중 상속이 됨
상속의 부모 생성자 호출
부모 객체를 상속하는 자식 객체가 생성될 때, 부모 생성자를 호출하며 메모리 상에도 부모 객체가 존재함
자식 객체는 생성된 부모 객체를 참조함
자식 생성자의 맨 첫줄에서 부모 생성자가 자동적으로 호출됨
부모 클래스에 기본 생성자가 없다면,
super()
메소드를 이용해 호출해주어야 함부모 생성자가 호출되지 않을 시에 컴파일 에러가 남
메소드 재정의 (@Override)
상속받은 메소드가 자식 클래스에서 사용하기 적절하지 않다고 판단할 때, 부모 메소드의 시그니처를 그대로 물려받아 동일한 메소드를 재정의할 수 있음
메소드 재정의 (오버라이딩) 의 규칙
부모 메소드와 동일한 시그니처(리턴 타입, 메소드 이름, 매개변수 리스트)를 가져야 한다.
접근 제한을 더 강하게 오버라이딩할 수 없다. (
public
->private
)새로운 예외(Exception)를 throws할 수 없다.
@Override 애노테이션
부모 메소드의 시그니처를 올바르게 물려받았는지 검사하고 그렇지 않을 시에 컴파일 에러를 낸다.
상속 시 부모 메소드의 호출
super
키워드를 이용해서 가능하다.
final 클래스와 final 메소드의 상속
final 클래스의 상속
final
클래스는 상속이 불가능하다. 부모 클래스가 될 수 없다.
final 메소드의 상속
final
메소드는 오버라이딩할 수 없다.final
필드나 메소드의 원형으로는 사용하는데 문제 없다.
protected 접근 제한자
protected
는 필드, 생성자, 메소드에 적용할 수 있다.다른 패키지에 소속된 클래스에서는 접근할 수 없다. (default와 같음)
단, 다른 패키지여도 자식 클래스에서는 접근 가능하다.
타입 변환과 다형성
다형성을 위해 자바는 부모 클래스로 타입 변환을 허용한다.
모든 자식은 부모 객체로 타입 변환할 수 있다.
이것을 응용하면 상위 타입에 대해 다양한 하위 타입을 적용하여 다형성을 이용할 수 있다.
자동 타입 변환
부모 클래스 변수 타입에 자식 클래스 변수를 할당하면 자식에서 부모로 자동으로 타입이 변환된다.
변수 뿐 아니라, 상위 타입의 파라미터에도 하위 타입의 인자를 넣으면 자동적으로 상위 타입으로 타입이 변환된다.
바로 위의 부모가 아니어도 하위 타입이기만 하면, 자동 타입 변환은 적용된다.
자동 타입 변환된 부모 클래스에서 자식 클래스에 의해 오버라이드된 메소드를 호출하면, 오버라이드된 메소드가 호출된다.
다형성(Polymorphism)과 관련이 있기 때문에 매우 중요하다.
강제 타입 변환
자식 클래스에서 부모 클래스로 자동 타입 변환이 일어났던 객체를 다시 강제 타입 변환을 이용하여 자식 클래스로 돌릴 수 있다.
자식 클래스에 선언된 메소드를 반드시 사용해야 한다면 강제 타입 변환을 이용하면 된다.
객체 타입 확인(instanceof)
지금 다루는 객체가 자동 타입 변환이 되어 부모 클래스가 된 것인지 아니면 처음부터 부모 클래스로 생성되었는지 궁금할 수 있다. 이럴 때, instanceof
를 사용하여 이 객체의 타입을 확인할 수 있다.
객체명
instanceof타입명
추상 클래스
추상 클래스는 객체로 실체화할 수는 없지만, 특정한 객체들의 공통적인 부분을 모아놓은 클래스이다. 여기서 특성은 필드와 메소드를 말한다. 추상 클래스는 인스턴스를 생성할 수 없지만, 특정 클래스의 부모 클래스로서 활용된다.
추상 클래스의 구체적 용도
실체 클래스들의 공통된 필드와 메소드의 이름을 통일할 목적
실체 클래스를 작성할 때 시간을 절약
공통적인 특성을 갖는 추상 클래스를 부모로 상속하면 중복 코드가 적어져 시간이 절약된다.
설계 단계에서 추상 클래스를 미리 설계하면 시간이 많이 절약된다.
추상 클래스의 선언
추상 클래스의 생성자
인스턴스화 될 수 없기 때문에 생성자가 필요 없다고 생각할 수 있으나, 자식 클래스에서는 반드시 부모 클래스의 생성자를 호출해야 하므로 추상 클래스 역시 생성자가 반드시 필요하다.
추상 메소드와 오버라이딩
모든 자식에게 같은 메소드가 적용되어도 상관없다면 오버라이딩을 할 필요가 없겠지만, 자식에 따라 다른 메소드가 필요하면 오버라이딩을 하면 된다.
더 나아가 모든 자식에게 시그니처는 같지만 실제 구현은 각각 다른 메소드가 필요할 수도 있다. 이럴 때 추상 메소드를 활용하면 된다.
책에서는 동물의 울음소리를 예로 들었다. 강아지, 고양이, 코끼리 모두
울기
라는 공통적인 행위가 존재하지만, 그에 따른 소리는 각각 달라야한다. 세 객체에게울기
라는 행위는 공통적이지만 그 소리는 공통적인 부분이 없는데 억지로 추상 클래스에 빈 메소드를 작성하거나 하면 나중에 실수로 오버라이드를 깜빡하여 울음소리를 입력하지 않을 수도 있다. 이런 경우는 반드시 오버라이드를 하도록 추상 메소드로 선언해주자.
[public | protected] abstract 리턴타입 메소드명(매개변수, ...);
Last updated