'extends'라는 자바 예약어로 부모 클래스를 상속 받을 수 있다. 부모 클래스를 상속 받은 자식 클래스는 부모 클래스에 선언되어 있는 public, protected 변수, 메소드를 자신의 변수, 메소드처럼 사용 가능하다.
접근 제어자가 없거나 private으로 선언된 것들은 자식 클래스에서 사용할 수 없다.
자바에서는 단일 상속만 가능하다. 즉, extends 예약어 뒤에 하나의 클래스만 쓸 수 있다.
자식 클래스에서 부모 클래스에 있는 메소드와 동일하게 선언하는 것을 메소드 오버라이딩이라고 한다.
접근제어자, 리턴 타입, 메소드 이름, 파라미터 타입과 개수 이 4가지가 모두 일치(=동일한 signature를 가짐)해야 메소드 오버라이딩이다.
오버라이딩을 할 때, 자식 클래스의 메소드는 부모 클래스 메소드의 접근 제어자보다 더 접근 범위를 축소해서는 안된다.
예를 들면, 부모 클래스에서 오버라이드하려는 메소드가 public으로 선언 되어있는데, 그것을 오버라이드 할때 private, protected 등으로 바꾸는 것이 불가능하다.
package javaonly;
public class Parent {
public Parent() {
System.out.println("Parent Constructor");
}
public void printName() {
System.out.println("printName() - Parent");
}
}
package javaonly;
public class Child extends Parent{
public Child() {
System.out.println("Child Constructor");
}
@Override
void printName() {
System.out.println("printName - Child");
}
}
이런 경우에서, Child 클래스의 printName 선언 부분에서 ''printName()' in 'javaonly.Child' clashes with 'printName()' in 'javaonly.Parent'; attempting to assign weaker access privileges ('package-private'); was 'public'' 이런 에러가 발생한다.
하지만 반대로, 자식 클래스에서 부모 클래스보다 접근 범위를 확대하는 것은 허용된다.
상속을 받으면 다음과 같은 인스턴스 선언이 가능하다.
Parent p_obj = new Child();
Child 클래스에서는 Parent 클래스에 있는 메소드, 변수에 접근할 수 있다.
하지만 아래와 같은 코드를 작성하면 컴파일 에러가 발생한다.
Child child = new Parent();
자식 클래스 참조 변수에 부모 클래스 인스턴스를 담고 싶다면 명시적 형변환(casting)을 해주어야 한다.
Child child = (Child)(new Parent());
이렇게 casting을 하면 컴파일은 되지만, 런타임에 exception이 발생한다.
'[instance 이름] instanceof [클래스이름]' 이 코드로 어떤 인스턴스가 해당 클래스에 속하는지 아닌지 여부 boolean으로 알 수 있다.
다음과 같이 코드를 짜서 실행해보면
package javaonly;
public class Inheritance {
public static void main(String[] args) {
Parent parent = new Parent();
Child child = new Child();
boolean b1 = parent instanceof Child;
boolean b2 = child instanceof Parent;
System.out.println("parent is Child? " + b1);
System.out.println("child is Parent? " + b2);
}
}
parent is Child? false
child is Parent? true
즉, 자식 클래스는 부모 클래스에 속한다. 그래서 부모 클래스 변수에 자식 클래스 인스턴스를 넣을 수 있는 것이다.
하지만 반대는 성립하지 않는다.
이러한 특징 때문에 if문과 instanceof 키워드로 인스턴스의 종류를 판단할 때는 하위에 있는 자식 클래스인지부터 검사해야한다.
Ploymorphism.
Parent p = new Parent();
Parent c = new Child();
위와 같이 형변환을 하여 인스턴스를 선언하여도, 실제 호출되는 메소드는 실제 인스턴스에서 오버라이딩한 메소드가 호출이 된다.
선언시에는 모두 같은 클래스로 선언했지만, 실제 호출되는 것은 실제 인스턴스에 따라 다르므로 이를 다형성이라고 한다.