객체지향 프로그래밍 언어인 자바에서 다형성(polymorphism)이란 같은 타입이지만 실행 결과로 다양한 객체를 대입할 수 있는 성질을 말한다
부모 타입에는 모든 자식 객체가 대입될 수 있다
Class Car {
}
class Tire extends Car {
}
Car라는 부모 class를 자식클래스인 Tire에서 상속을 받은 경우에는
Tire t = new Tire();
Car c = t;
Car c = new Tire();
자식 객체를 생성해서 참조변수를 부모의 참조변수에 대입하거나 부모의 참조변수 생성한 자식 객체를 대입할 수 있다
이때 발생하는 것이 자동 타입 변환(promotion) 이며 자식 객체는 부모 타입으로 자동 변환된다
코드로 살펴보자
public class A {
} //부모 클래스 A
public class B extends A{
} // A클래스 상속
public class C extends A {
} // A클래스 상속
public class D extends B{
} // B클래스 상속
public class E extends C{
} //E클래스 상속
가장 상위 부모 클래스인 A클래스를 B,C가 상속받고 D는 B클래스, E는 C클래스를 상속받는 구조다
package exam_promotion;
public class Promotion_example {
public static void main(String[] args) {
B b = new B();
C c = new C();
D d = new D();
E e = new E();
A a1 = b;
A a1 = c;
A a1 = d;
A a1 = e;
B b = d;
C c = e;
}
}
위의 코드를 보면 가장 상위의 부모 클래스인 A타입의 참조변수에 다른 하위 클래스의 객체를 대입할 수 있다
그리고 B클래스와 C클래스를 각각 상속한 D와 E클래스도 대입되는 것을 확인할 수 있다
자동으로 타입이 변환된 이후에는 어떻게 되는걸까?
부모 타입으로 자동 타입 변환이 된다면 부모 클래스에 선언된 필드와 메소드만 접근이 가능하게 된다
class Car {
void method1(){}
void method2(){}
}
class Tire extends Car {
void method2(){} //overriding
void method3(){}
}
부모 클래스인 Car를 Tire클래스에서 상속받은 경우를 보자
public static void main(String[] args) {
Tire t = new Tire();
//자식 객체 생성
Car c = t;
//부모의 참조변수에 자식객체 대입
c.method1();
c.method2();
//부모 클래스에 선언된 method1, method2는 호출 가능
//method2는 자식 클래스에 overriding되어 있기 때문에
//자식 클래스에서 호출한다
c.method3();
//자식 클래스에 선언된 method3은 호출 불가능
}
method2의 경우에는 자식클래스에 재정의된 메소드가 호출된다.
즉, 부모 타입으로 호출해도 자식 클래스에서 호출하여 실행된다
public class Parent {
public void method1() {
System.out.println("parent method1");
}
public void method2() {
System.out.println("parent method2");
}
}
부모 클래스인 Parent 클래스를 만들었다
public class Child extends Parent {
@Override
public void method2() {
System.out.println("child method2");
}
public void method3() {
System.out.println("child method3");
}
}
자식 클래스인 Child 클래스는 Parent 클래스를 상속한다
여기서 method2는 Parent 클래스의 method2를 overriding 했고 method3은 Child 클래스에만 선언된 method다
이 경우 콘솔에 어떻게 출력이될까?
public class ChildExecute {
public static void main(String[] args) {
Child child = new Child();
Parent parent = child;
parent.method1();
parent.method2();
}
}
console
parent method1
child method2
콘솔을 보면 method2는 overriding된 Child class의 method가 출력된 걸 확인할 수 있다
여기서 parent.method3()을 호출하면 에러가 뜬다
그 이유는 Child객체를 생성해 부모 타입에 대입을 했기 때문에 Child 클래스에만 선언된 method3을 호출할 수 없기 때문이다
요약하자면,
자식객체를 부모객체로 타입 변환시킨 경우에는 부모 클래스에 선언된 method에만 접근이 가능하다. 하지만 자식 클래스에 overriding된 method가 있다면 우선적으로 자식 클래스에 overriding된 method가 실행된다