자바의 다형성에 대한 이해가 부족해서 다시 공부하고 나중에 또 까먹을까봐 다시 정리해둔다.
다형성: 여러가지 형태를 가질 수 있는 능력.
더 구체적으로 : 조상클래스의 타입의 참조 변수로 자손 클래스의 인스턴스를 참조할 수 있다.
특정 클래스가 다른 클래스를 상속받으면 이는 자식클래스와 부모클래스의 관계를 가진다.
여기서 무조건! 자식 클래스는 부모 클래스보다 같거나 더 많은 멤버를 가진다.
그런데 만약 참조변수는 부모클래스 타입으로 하고, 인스턴스는 자손 클래스 타입으로 생성한다면?
이것이 다형성이다. 즉 부모 클래스의 참조변수가 자식 클래스의 인스턴스를 참조할 수 있다.
모든 클래스의 부모인 Object클래스와 내가 정의한 PolyTest 클래스를 예로 들어보자 (내가 정의하던 누가 정의하던 모든 클래스는 Object클래스의 자손이다.)
class Polytest{
public void polyMethod(){
System.out.println("poly poly");
}
}
public class Test{
public static void main(String[] args){
Object obj = new PolyTest(); //부모클래스 타입 참조변수가 자식클래스 인스턴스 참조
//obj.polyMethod(); 에러!!!!
}
}
그런데 저렇게 부모클래스타입 참조변수가 자식클래스타입의 인스턴스를 참조하게 되면 obj는
PolyTest 클래스의 인스턴스를 참조하고 있음에도 PolyTest의 메소드 polyMethod()에 접근 할 수 없다.
왜냐하면 참조변수의 타입에 따라 사용할 수 있는 멤버의 개수가 달라진다!
(물론 자식의 오버라이딩된 메소드는 접근할 수 있지만 여기서는 다루지 않는다.)
즉 자식클래스 인스턴스를 부모클래스 타입의 참조변수가 참조하는 것은 일종의 가림막이 생기게 되는 것이다.
=>>>> 참조변수의 타입에 따라서 사용할 수 있는 멤버변수의 개수가 달라진다.
=>>>> 참조변수.멤버 이런식으로 접근하므로 참조변수가 멤버에 접근하는 범위를 결정한다.
그렇다면 반대는 가능할까? 즉
PolyTest poly = new Object();
위처럼 자식클래스 타입의 참조변수로 부모클래스 타입의 인스턴스를 참조할 수 있을까?
이것은 불가능하다.
형변환
부모 -> 자식
자식 -> 부모
요렇게 참조변수의 형변환이 가능하다.
여기서 자식 -> 부모 의 형변환은 업캐스팅이라고 한다. 이는 형변환을 생략할 수 있다.
위에서 강조한 것처럼 << 참조변수가 멤버에 접근하는 범위를 결정하기 때문이다. >>
즉 자식 -> 부모로 참조변수형이 변환된다면 변환된 참조변수는 호출할 수 있는 멤버의 개수가 더 적어지는 것이다.
class Polytest{
public void polyMethod(){
System.out.println("poly poly");
}
}
public class Test{
public static void main(String[] args){
Object obj = new Object();
PolyTest poly = new PolyTest();
obj = poly; //업캐스팅. obj = (Object)poly; 와 같다.
}
}
부모가 1, 2, 3을 가지고 있고, 자식클래스가 1, 2, 3, 4, 5를 가지고 있다면
부모클래스형 참조변수로 변하기 전의 참조변수는 1, 2, 3, 4, 5에 접근할 수 있었다. 그런데
부모클래스형 참조변수로 형변환되면 1, 2, 3에만 접근할 수 있다. 가림막이 생기니까!
(다시 강조: 참조변수가 멤버에 접근하는 범위를 결정 )
이것은 문제 될 것이 없다. 1 , 2, 3, 4, 5모두를 호출할 수 있는 친구가
1 , 2, 3을 호출 못할 일은 없으니까.
그런데 반대로 부모 -> 자식으로 형변환될 때는 명시를 해줘야한다.
class Polytest{
public void polyMethod(){
System.out.println("poly poly");
}
}
public class Test{
public static void main(String[] args){
Object obj = new Object();
PolyTest poly = new PolyTest();
poly = (PolyTest)obj; // 업캐스팅
}
}
코드를 보면 (PolyTest)로 형변환을 하는 것을 알 수 있다.
왜냐하면 obj가 PolyTest형(자식클래스형) 참조변수가 되면 더 많은 기능에 접근할 수 있는 발판?을 가지게 된다.
즉 4, 5에 접근을 못하게 하던 가림막이 없어지는 것이다.
하지만 물론 위의 코드에서 처럼 애초에 Object형 인스턴스 였던 obj가 가림막이 사라진다해서 PolyTest의 기능을 쓸 수 있는 것은 아니다.
class Polytest{
public void polyMethod(){
System.out.println("poly poly");
}
}
public class Test{
public static void main(String[] args){
Object obj = new Object();
PolyTest poly = new PolyTest();
poly = (PolyTest)obj; // 업캐스팅
obj.polyMethod(); // 컴파일 시에는 에러 안난다. 실행하면 에러!!!
}
}
위의 코드처럼 실행을 하면 에러가 난다. 왜냐하면 obj의 인스턴스는 Object형이고 Object클래스에는 polyMethod()라는 메소드가 없다.....
이 불편해 보이는 관계를 통해서 다형성을 구현하면 좋은 객체지향 프로그래밍을 할 수 있다.
그것을 배우기 전에 이해하기 위해 기록.
'java' 카테고리의 다른 글
Serializable (0) | 2021.11.21 |
---|---|
인터페이스 - 느슨한 결합력 (0) | 2021.04.25 |
Java - 4강 추상 클래스, 템플릿 메서드, final예약어 (0) | 2021.02.21 |
Java -3강 다형성, instanceof, 다운캐스팅 (0) | 2021.02.21 |
Java - 2강 상속, 묵시적 클래스 형 변환, 가상 메서드 (0) | 2021.02.21 |