다형성은 사용 방법은 동일하지만 다양한 객체를 이용해서 다양한 실행결과가 나오도록 하는 성질이다.
자동 타입 변환은 프로그램 실행 도중에 자동적으로 타입 변혼이 일어나는 것을 말한다.
자동 타입 변환은 다음과 같은 조건에서 일어난다
부모타입 변수 = 자식타입;
Animal과 Cat 클래스가 상속관계에 있다고 가정하고 예를 들어보면,
Animal animal = cat;
위와 같이 사용 가능하다.
이와 같이 부모타입으로 자동 타입 변환된 이후에는 부모 클래스에 선언된 필드와 메소드만 접근이 가능하다. 그러나 메소드가 자식 클래스에서 새로 생성되었다면, 자식 클래스의 메소드가 대신 호출 된다.
ex )
class Parent {
void method1() { ... }
void method2() { ... }
}
class Child extends Parent {
void method2() { ... } // 오버라이딩
void method3() { ... }
}
class ChildExample {
public static void main(String[] args) {
Child child = new Child;
Parent parent = child; // 자동 타입 변환
parent.method1();
parent.method2();
parent.method3(); // 호출 불가능
}
}
Child 객체는 method3 메소드를 가지고 있지만, Parent 타입으로 변환된 이후에는 method3을 호출할 수 없다.
강제 타입 변환은 부모 타입을 자식 타입으로 변환하는 것을 말한다. 자식 타입이 부모타입으로 자동 타입 변환한 후 다시 자식타입으로 변환할 때 강제 타입 변환을 사용할 수 있다.
사용하는 방법)
자식타입 변수 = (자식타입) 부모타입;
자동 타입 변환은 위에 말했던 것처럼 부모에 선언된 필드와 메소드만 사용 가능하다는 제약사항이 따르는데 만약 자식에 선언된 필드와 메소드를 꼭 사용해야 한다면 강제 타입 변환을 해서 다시 자식타입으로 변환한 후에 필드와 메소드를 사용하면 된다.
ex)
class Parent {
String field1;
void method1() { ... };
void method2() { ... };
}
// 상속
class Child extends Parent {
String field2;
void method3() { ... };
}
class ChildExample {
public static void main(String[] args) {
Parent parent = new Child(); // 자동타입변환
parent.field1 = "xxx";
parent.method1();
parent.method2();
parent.field2 = "yyy" //불가능
parent.method3(); //불가능
Child child = (Child) parent;
child.field2 = "yyy"; // 가능
child.method3(); // 가능
}
}
instanceof연산자는 어떤 객체가 어떤 클래스의 인스턴스인지 확인하기 위한 연산자이다. 강제 타입 변환은 자식 타입이 부모 타입으로 변환되어 있는 상태에서만 가능하기 때문에 처음부터 부모타입으로 생성된 객체는 자식 타입으로 변환할 수 없다.
ex)
Parent parent = new parent;
Child child = (Child) parent; // 강제 타입 변환 불가능
instanceof 연산자의 왼쪽에는 객체가 오고 오른쪽에는 타입이 온다. 왼쪽의 객체가 오른쪽의 타입으로 생성된 객체라면 true를 리턴하고 그렇지않으면 false로 리턴한다.
메소드 내에서 강제 타입 변환이 필요할 경우 반드시 매개값이 어떤 객체인지 instanceof 연산자로 확인하고 안전하게 강제 타입 변환을 해야 한다.