동적 바인딩이란?
컴파일 시점에서 실행될 것으로 예상되는 코드와
실제 실행 시점에서 해당 객체의 타입 기준으로 메서드가 달라지는 것을 의미한다.
즉, 쉽게 말하면 실행 예상되는 코드와 실제 실행된 코드가 달라지는 것이다.
나는 상속을 배우고, 레퍼런스 형변환을 배우면서 의문이 생겼다.
Parent라는 슈퍼클래스와 이 클래스를 상속받는 Child라는 서브클래스가 있다고 치자.
Child클래스는 상속으로 인해 Parent클래스의 멤버에 접근 가능 하다. 하지만 Parent 클래스는
Child클래스에 접근할 수 없다.
이때 의문이 들었다.
업캐스팅을 하면 참조 영역이 축소되기 때문에 서브 클래스에 접근할 수 없다.
그렇다면 왜 업캐스팅이 필요한가?
어차피 슈퍼클래스는 서브클래스에 접근할 수 없는게 아닌가?
이에 대한 의문은 바로 동적 바인딩으로 해소되었다.
✍
public class Test10 {
public static void main(String[] args) {
SmartPhone s = new SmartPhone("010-1111-1111", "안드로이드");
Phone p = new Phone("010-2222-2222");
p.call();
p.sms();
// p.kakao(); // 컴파일 오류 발생
s.call();
s.sms();
s.kakao();
}
}
class Phone { // 슈퍼클래스
String number;
public Phone(String number) {
this.number = number;
}
public void call() {
System.out.println("전화 걸기");
}
public void sms() {
System.out.println("문자 보내기");
}
}
class SmartPhone extends Phone { // 서브클래스
String os;
public SmartPhone(String number, String os) {
super(number);
this.os = os;
}
public void kakao() {
System.out.println("카톡 보내기");
}
@Override
public void call() {
System.out.println("전화 걸기! 오버라이딩 된 메서드 입니다.");
}
@Override
public void sms() {
System.out.println("문자 보내기! 오버라이딩 된 메서드 입니다.");
}
}
위와 같은 코드가 있다.
이때 SmartPhone 객체는 Phone을 상속받기 때문에 Phone의 멤버에 접근이 가능하다.
Phone객체는 SmartPhone 메서드에 접근이 불가능 하다.
이때 업캐스팅을 하여 결과를 살펴보자 .
public static void main(String[] args) {
SmartPhone s = new SmartPhone("010-1111-1111", "안드로이드");
Phone p = new Phone("010-2222-2222");
p.call();
p = s; // 업캐스팅
p.call();
}
자, 이런 코드가 있다. 이때 출력결과는 어떻게 될까?
p.call() 이라는 동일한 코드가 작성되어 있다. Phone 객체의 참조변수 p가 call() 메서드를 호출하였으니
"전화 걸기"라는 코드가 출력될 까?
💻 결과는 !
전혀 다른 결과가 출력되었다.
위의 p.call()은 전화 걸기
아래의 p.call()은 SmartPhone 객체의 오버라이딩 된 call()메서드가 호출되었다.
그 이유는, 업캐스팅으로 인해 Phone 클래스의 레퍼런스가 서브클래스의 인스턴스를 참조하기 때문이다.
컴파일 시점에서는 Phone 클래스의 call() 메서드가 호출되지만,
실제로 참조변수 p에 저장된 인스턴스는 Phone 인스턴스가 아니라 SmartPhone의 인스턴스다.
그래서 실제 실행 시점에서는 SmartPhone 클래스의 오버라이딩된 call()메서드가 호출되는 것이다.
서브클래스의 인스턴스를 슈퍼클래스의 타입으로 변환하는 것이다.
그러므로, 업캐스팅 이후에는 Phone의 레퍼런스가 메서드를 호출하면, 서브클래스의 메서드가 호출된다. (슈퍼클래스의 레퍼런스가 서브클래스의 인스턴스를 참조하기 때문!)
그렇기 때문에 ! 단순히 상속관계에서 슈퍼클래스가 서브클래스의 메서드에 접근하지 못 하는 것과
레퍼런스 형변환으로 인해 참조 영역이 축소되는 것과는 차이가 있다.
'개발 > Java' 카테고리의 다른 글
[Java] final 키워드 (0) | 2023.02.14 |
---|---|
[Java] 다형성 (0) | 2023.02.11 |
[Java] 클래스들의 관계 (0) | 2023.02.11 |
[Java] 레퍼런스 형변환 (0) | 2023.02.10 |
[Java] 상속에서의 생성자 (0) | 2023.02.09 |