-
[Java] 다형성과 바인딩Language/Java 2024. 10. 21. 21:10
최근 정보처리기사 실기 시험을 보았다.
문제집에서 풀던 기출 문제보다 어려웠다. 허점이 많은 상태에서 시험을 봤던 것 같다.
Java 문제 중 기억에 남는 문제가 하나 있어서 궁금해서 찾아보다가 정리를 해보면 좋겠다는 생각을 했다.해당 문제는 다형성에 대한 것이었다(참고로, 틀렸다).
정확한 숫자는 기억이 안나지만, 아래와 같은 문제였다.class Parent { int b = 2; public int print() { return b * 4; } } class Child extends Parent { int b = 3; @Override public int print() { return b * 7; } } class Main { public static void main(String[] args) { Parent p = new Child(); Child c = new Child(); System.out.println(p.print() + p.b + c.print() + c.b); } }
답은 21(p.print())+2(p.b)+21(c.print())+3(c.b) 와 같이 계산한 값이 된다.
다형성에 대한 개념과 Java의 바인딩(동적/정적)을 알지 못하면 풀 수 없는 문제였다.
어떤 이유로 p.b의 값이 2인데도 p.print()의 값은 21이 나오는걸까?다형성(polymorphism)
여러 가지 형태를 가질 수 있는 능력
(Java에서는) 조상 클래스의 타입의 참조변수로 자손 클래스의 인스턴스를 참조할 수 있다.
예를 들어,
class Tv{ int channel = 6; void power(){power=!power;} } class SmartTv extends Tv{ int channel = 9; void channelUp(){++channel;} }
과 같은 간단한 코드가 있다고 해보자.
기본적인 방식의 인스턴스 생성
기본적인 방식으로 인스턴스를 생성한다면 다음과 같을 것이다.
Tv tv = new Tv(); SmartTv smartTv = new SmartTv();
다형성의 특징을 이용한 인스턴스 생성
그러나 다형성의 특징을 반영하면 다음과 같은 코드도 동작한다.
Tv tv = new SmartTv();
도 가능하다는 것이다. 중요한 것은, 그 반대는 성립되지 않는다는 것이다.
SmartTv타입으로 Tv 인스턴스를 참조할 수는 없다. 그 이유는 부모 타입보다 자식 타입이 가진 변수와 메서드의 개수가 항상 같거나 많기 때문에 참조변수가 사용할 수 없는 메서드가 존재하기 때문이다.
어떻게 문제의 p.print()가 21이 되는 것일까?
그것의 비밀은 변수와 메서드의 바인딩 방식 차이에 있다.
정적/동적 바인딩
정적 바인딩(Static Binding)
- 메서드나 변수의 참조를 컴파일 시점에 결정한다.
- 레퍼런스 타입을 따라간다. (선언 타입)
- 적용 대상 : 인스턴스 변수와 private/final/static
동적 바인딩(Dynamic Binding)
- 어떤 메서드를 호출할지 런타임 시점에 결정한다.
- 실제 객체 타입을 따라간다. (생성 타입)
- 적용 대상 : 오버라이딩된 메서드
변수는 정적 바인딩 => 레퍼런스 타입(Parent)
오버라이딩된 print메서드는 동적 바인딩 => 실제 객체 타입(Child)
이므로 p.b(변수)는 Parent 타입(참조타입)의 b변수를 따라 2가 되지만, p.print(메서드)는 Child 타입(실제 객체 타입)의 print가 호출되어 21이 되는 것이다.
p.b가 2인데 왜 print()는 14가 아니고 21일까?
Parent의 b는 2를 가리키고 있지만 Child의 print함수를 호출할 때는 전혀 사용되지 않는다.
같은 이름으로 정의했음에도 값이 독립적인 것처럼 느껴지는 이유는 변수에서는 변수 숨김 이라는 개념으로 인해 같은 이름의 변수가 선언된 경우, 부모의 변수가 가려지기 때문이다.
오버라이딩은 메서드에만 적용되는 개념이므로, 변수가 오버라이딩 된다거나, 재할당되지는 않는다.단지 자식 클래스에서 부모 클래스의 변수를 참조할 수 없을 뿐이다. 굳이 접근하고 싶다면 ((Parent) c).b과 같은 캐스팅(형변환)을 통해 접근할 수 있다.
생각
시험을 보고 집에 가면서 객체 지향 제대로 공부할 걸 그랬다며 후회했는데, 오늘 이렇게 찾아보면서 객체 지향에 대해 공부하고 갔어도 틀리지 않았을까 생각하게 되었다ㅎㅋㅎㅋ..
이 문제는 다형성이 포인트가 아니라, 변수/메서드 바인딩이 포인트인 것으로 보인다.처음 그 문제를 보며 들던 여러가지 의문을 해소할 수 있는 시간이었다. 보람찬 시간~~
'Language > Java' 카테고리의 다른 글
[IDEA] 디버깅 모드 (0) 2024.10.22 [Java의 정석] 2-2. 변수의 타입 (1) 2024.10.21 [우테코 프리코스] 1주차 회고 (3) 2024.10.19 [우테코 프리코스] Console.class가 무엇 (0) 2024.10.18 [우테코 프리코스] NsTest가 무엇 (1) 2024.10.17