클래스의 변환은 상속 관계에 있는 클래스 사이에서 발생한다. 자동 타입 변환은 프로그램 실행 도중에 자동적으로 타입 변환이 일어나는 것을 말하는데 자동 타입 변환은 아래와 같은 조건에서 일어난다.
Parent a = new Child();
또는
b = new Child();
parent a = b;
즉, 자식 타입 객체만이 부모타입으로 자동 타입 변환이 일어날 수 있다. Child 클래스로 부터 Child객체를 생성하고 이것을 Parent 변수에 대입하면 자동 타입 변환이 일어난다.
자동 타입 변환의 개념은 자식은 부모의 특징과 기능을 상속받기 때문에 부모와 동일하게 취급될 수 있다는 것이다. 예를 들어, 고양이가 동물의 특징과 기능을 상속받았다면 '고양이는 동물이다.'가 성립한다.
위 그림에서 알 수 있듯이, a는 부모 타입이므로 부모 객체를 참조하는 것이 맞지 않느냐라고 생각할 수도 있지만 그렇지 않고, a와 b 모두 자식 객체를 참조한다.
또한 바로 위의 부모가 아니더라도 상속 계층에서 상위 타입이라면 자동 타입 변환이 일어날 수 있다.
D객체는 B와 A 타입으로 자동 타입 변환이 될 수 있고, E 객체는 C와 A 타입으로 자동 타입 변환이 될 수 있다. 그러나 D 객체는 C 타입으로 변환될 수 없고, 마찬가지로 E 객체는 B타입으로 변환될 수 없다. 상속관계가 아니기 때문이다.
package TestPackage;
classA{}
classBextendsA{}
classCextendsA{}
classDextendsB{}
classEextendsC{}
publicclassTest{
publicstaticvoidmain(String[] args){
B b = new B();
C c = new C();
D d = new D();
E e = new E();
A a1 = b;
A a2 = c;
A a3 = d;
A a4 = e;
B b1 = d;
C c1 = e;
B b3 = e; //상속 관계가 아니므로 컴파일 에러 발생
C c2 = d; //상속 관계가 아니므로 컴파일 에러 발생
}
}
다형성과 관련있는 중요한 자동 타입 변환의 성질 부모 타입으로 자동 타입 변환된 이후에는 부모 클래스에 선언된 필드와 메소드만 접근이 가능하다. 변수는 자식 객체를 참조하지만 변수로 접근 가능한 멤버는 부모 클래스 멤버로만 한정된다. 그러나 예외가 있는데, 메소드가 자식 클래스에서 재정의되었다면 자식 클래스의 메소드가 대신 호출된다.
필드의 타입을 부모 타입으로 선언하면 다양한 자식 객체들이 저장될 수 있기 때문에 필드 사용 결과가 달라질 수 있다.
이것이 필드의 다형성이다.
예를 들어 자동차를 구성하는 부품은 언제든지 교체할 수 있다. 부품은 고장이 날 수도 있고 성능이 더 좋은 부품으로 교체되기도 한다. 객체지향 프로그래밍에서도 마찬가지이다.
이를 자동차 클래스에 포함된 타이어 클래스를 생각해보면 자동차 클래스를 처음 설계할 때 사용한 타이어 객체는 언제든지 성능이 좋은 타이어 객체로 교체할 수 있어야 한다. 새로 교체된 타이어 객체는 기존 타이어와 사용 방법은 동일하지만 실행결과는 더 우수하게 나와야 할 것이다. 이것을 프로그램으로 구현하기 위해서 상속과 오버라이딩, 타입 변환을 이용한다.
Driver driver = new Driver();
Vehicle vehicle = new Vehicle();
driver.drive(vihicle);
만약 Vehicle의 자식 클래스인 Bus 객체를 drive() 메소드의 매개값으로 넘겨주면
driver.drive(bus);
drive() 메소드는 Vehicle 타입을 매개 변수로 선언했지만, Vehicle을 상속받는 Bus 객체가 매개값으로 사용되면 자동 타입 변환이 발생한다.
매개 변수의 타입이 클래스일 경우, 해당 클래스의 객체뿐만 아니라 자식 객체까지도 매개값으로 사용할 수 있다는 것이다. 즉, 매개값으로 어떤 자식 객체가 제공되느냐에 따라 메소드의 실행결과는 다양해질 수 있다. 자식 객체가 부모의 메소드를 재정의했다면 메소드 내부에서 오버라이딩된 메소드를 호출함으로써 메소드의 실행결과는 다양해진다.