우리는 자동차라는 클래스를 생성했다. 근데 ‘소나타’ 라는 새로운 클래스를 작성해야 한다 가정하자. 소나타는 자동차가 가지고 있는 모든 정보를 가지고 있다. 우리는 과연 전부 새로운 코드로 작성한 ‘소나타’ 클래스를 만들어야 할까?
class SubClass extends SuperClass{} // 상속은 extends 연산자를 사용한다.
조상 클래스가 변경된다면 자식 클래스에도 자동적으로 영향 , But 자식 클래스의 변경은 조상 클래스에게 영향이 없다.
- 멤버와 타입의 상속
- 상속은 멤버(변수와 메서드)와 타입을 물려준다. (생성자와 초기화 블럭은 상속의 대상이 아닌다.)
- 단일 상속
- C++은 하나의 클래스가 여러 조상 클래스로부터 상속 가능한 다중 상속을 지원한다.
- 하지만 자바에서는 오직 하나의 조상 클래스로부터만 상속이 가능한 단일 상속을 지원한다.
class LgTv{
int price;
}
class ApplceTv{
int price;
}
class MyTv extends LgTv,AppleTv{
// ???? price 변수를 누구로부터 상속받아야 하지?
}
위 예시에서 MyTv라는 클래스는 LgTv, AppleTv 2개의 조상 클래스를 가지고 있다. 과연 이런 상황에서 MyTv의 price 변수는 어떤 클래스로부터 상속받아야 할까?
- 위와 같은 상황이 다중 상속의 문제점이다. 자바는 이러한 고민거리를 해결하는 방법으로 다중 상속을 그냥 포기했다….
- 뒤에서 배우겠지만 인터페이스의 존재로 어느정도 다중 상속의 장점을 채우고 있다.
여담으로 우리 모두 시조가 있다…(몇대손…) 클래스도 부모와 자식 관계가 있다면 시조도 존재하지 않겠는가? → Object Class (모든 클래스의 시조)
class MyClass{} -> class MyClass extends Object{}
부모와 자식 관계는 지정하지만 클래스간 형제 관계라는 용어는 없다. 그 이유가 바로 이 Object 클래스 때문이다. 결국 모든 클래스는 형제 클래스이기 때문이다….
class 자동차{
void print(){
System.out.println("자동차");
}
}
class 람보르기니 extends 자동차{
// 나의 조상 클래스가 '자동차'이지만 명색이 람보르기니인데 자동차로 불리는 건.....
//나만의 print() 메서드를 정의하고 싶어
}
메서드의 선언부가 일치해야 한다.
- 메서드의 이름이 동일해야 한다.
- 매개변수가 같아야 한다.
- 반환 타입이 같아야 한다. (공변 반환 타입)
- 접근 제어자는 조상 클래스보다 좁은 범위로 변경할 수 없다.
- public > protected > (default) > private
- ex) 부모 클래스의 메서드의 접근 제어자가 public일 때 자식 클래스의 접근 제어자를 protected로 지정할 수 없다.
- 조상 클래스의 메서드보다 많은 수(넓은 범위)의 예외를 선언할 수 없다.
class Parent{
Parent createOne(){ return Parent();}
}
class Child extends Parent{
@Override
Child createOne(){ return Child();} // 공변 반환 타입 사용하여 오버라이딩
}
위에서 생성자는 상속 대상이 아니라고 했다.
상속이라는 것은 자손의 멤버와 조상의 멤버를 모두 합쳐 하나의 인스턴스가 생성된다. 이때 조상 클래스의 생성자가 호출되어야 하지만 기본적으로 생성자는 상속 대상이 아니다.
- 자식 클래스의 생성자에서 조상 클래스의 생성자가 먼저 호출되어 조상의 멤버들이 먼저 초기화되어야 한다.
- 자식 클래스 생성자에서 super()를 호출하지 않으면 컴파일러가 자동적으로 생성자의 첫줄에 삽입한다.
class Parent{
int x;
Parent(int x){
this.x = x;
}
}
class Child extends Parent{
int y;
Child(int y){
this.y = y;
}
}