관리 메뉴

클라이언트/ 서버/ 엔지니어 "게임 개발자"를 향한 매일의 공부일지

상속 14 - 메서드 오버라이딩 2 : 동적 바인딩과 오버로딩 vs 오버라이딩 본문

프로그래밍 언어/자바

상속 14 - 메서드 오버라이딩 2 : 동적 바인딩과 오버로딩 vs 오버라이딩

huenuri 2024. 12. 1. 23:54

메서드 오버라이딩에 대한 학습을 이어서 진행해보겠다. 벌써 11시 반이 다 되었지만 앞으로 3시간 안에 상속 단원의 개념 학습을 모두 마칠 생각이다. 

그래야 오늘 새벽에 연습문제를 대부분 풀고 상속 학습을 마칠 수 있을 것 같다. 오늘은 가능하면 JDBC 공부를 시작해보려고 한다.


 

 

 

 

동적 바인딩 : 오버라이딩된 메서드 호출

동적 바인딩(dynamic binding)은 실행할 메서드를 컴파일 시(compile time)에 결정하지 않고 실행 시(run time)에 결정하는 것을 말한다. 자바에서는 동적 바인딩을 통해 오버라이딩된 메서드가 항상 실행되도록 보장한다.

다음 그림은 동적 바인딩의 두 사례를 보여준다. 그림 의 왼쪽에서 main()에서 shape() 객체를 생성하고, paint() 메서드를 호출하면 Shape의 draw()를 호출하게 된다.

Shape a = new Shape();
a.print();	// paint()는 Shape의 draw()를 호출한다

 

 

 

 

 

하지만 위 그림의 오른쪽 코드를 보자. Circle 클래스에서 Shape의 draw()를 오버라이딩하였다. main()에서 Circle 객체를 생성하고 다음과 같이 b.paint()를 호출하면, 객체 b에 존재하는 2개의 draw() 중 어떤 것을 호출할지 결정하는 동적 바인딩이 일어난다.

Shape b = new Circle();
b.print();	// paint()는 Circle에서 오버라이딩한 draw()를 호출

 

 

그 결과 Shape의 paint() 메서드는 Shape의 draw()가 아닌 Circle의 draw()를 호출한다. 어디서 호출하든 동적 바인딩을 통해 항상 오버라이딩한 Circle의 draw()가 호출된다.


 

 

 

 

오버라이딩과 super 키워드

오버라이딩되어 있는 경우, 동적 바인디에 의해 항상 서브 클래스에 오버라이딩한 메소드가 호출됨을 설명했다. 그러면 슈퍼 클래스의 메서드는 이제 더 이상 쓸모없게 된 것인가? 아니다. 다음과 같이 서브 클래스에서 super 키워드를 사용하면 정적 바인딩을 통해 슈퍼 클래스의 멤버에 접근할 수 있다.

super.슈퍼클래스의멤버

 

 

super는 자바 컴파일러에 의해 지원되는 것으로 슈퍼 클래스에 대한 레퍼런스이다. super를 이용하면 슈퍼 클래스의 필드와 메서드 모두 접근 가능하다. 다음 그림은 super를 활용하는 사례를 보여준다. 특히 Circle 클래스의 다음 draw() 코드에 주목하라.

name = "Circle";	// Circle 클래스의 name에 "Circle" 기록
super.name = "Shape";	// Shape 클래스의 name에 "Shape" 기록
super.draw();	// Shape 클래스의 draw() 호출. 정적 바인딩

 

 

이 코드의 실행 결과 다음 그림과 같이 2개의  name 필드에 각각 다른 문자열이 들어있는 것을 볼수 있다.

 

 


 

 

 

 

메서드 오버라이딩

게임에서 무기를 표현하는 Weapon 클래스를 만들고 살상능력을 리턴하는 fire() 메서드를 작성하면 fire()는 1을 리턴한다.

 

 

 

대포를 구현하기 위해 Weapon을 상속받는 Cannon 클래스를 작성한다. Cannon은 살상능력이 10이다. fire() 메서드를 이에 맞게 오버라이딩한다. main()을 작성하고 오버라이딩을 테스트할 것이다.

 

 

 

 


 

 

 

 

 

오버로딩(overloading)과 오버라이딩(overriding)

오버로딩과 오버라이딩은 자바에서 다형성을 이루는 방법들이다. 오버로딩은 한 클래스나 송삭 관계에 있는 클래스들 사이에 메서드의 이름은 같지만, 매개변수 타입이나 개수를 다르게 메서드를 작성하는 경우이다. 오버라이딩은 상속 관계에서만 성립하지만 오버로딩은 동일한 클래스 내 혹은 상속 관계 둘 다 가능하다. 이 둘의 차이점을 다음 표에 정리하였다.

 


 

 

 

 

 

핵심 체크문제 풀기

 

 

문제 3번과 4번은 틀렸다. 그래도 두 문제를 맞혔으니 희망이 있다. 이제 코드를 직접 작성해보면서 출력 결과를 확인해보겠다.


 

문제 3번

 

1. 객체 생성

SuperObject b = new SubObject(); // 업캐스팅
  • SuperObject b : 부모 클래스 타입의 참조 변수 b 선언
  • new SubObject() : 자식 클래스 SubObject 객체 생성
  • 업캐스팅 : SubObject 객체를 SuperObject 타입으로 참조

2. b.paint() 호출

b.paint();
  • paint() 메서드는 부모 클래스인 SuperObject에서 정의된 메서드이다.
    따라서 b의 타입(즉, SuperObject)에 따라 부모 클래스의 paint()가 호출된다.

3. paint() 내부에서 draw() 호출

public void paint() {
    draw(); // draw() 메서드 호출
}
 
  • 다형성(Polymorphism):
    • draw() 메서드는 객체의 실제 타입에 따라 호출된다.
    • b는 SubObject 객체를 참조하고 있으므로, SubObject의 draw() 메서드가 호출된다.

4. SubObject의 draw() 실행

@Override
public void draw() {
    System.out.println("Sub Object");
}

 

  • 부모 클래스(SuperObject)의 draw() 메서드가 호출된다.
  • 출력: "Super Object"

 


 

 

 

코드 직접 실행하기

 

 

 

 

 

 

 

 


 

 

 

 

문제 4번

 

코드 분석하기

1. SubObject b = new SubObject();

동작

  • SubObject 타입 참조 변수 b 선언
    • b는 SubObject 객체를 참조
    • 이 경우, 참조 타입과 객체 타입이 모두 SubObject로 동일
  • new SubObject():
    • SubObject 클래스의 객체를 생성

결과

  • 메모리에 SubObject 객체가 생성되고, 참조 변수 b는 이를 참조

 

2. b.paint();

  • paint() 메서드는 자식 클래스 SubObject에서 오버라이딩되었으므로, 항상 자식 클래스의 메서드가 호출된다.

 

 

 

코드 직접 실행해보기

main()을 이처럼 바꾸었다.

 

 

 

 

결과는 이와 같다. 근데 책에는 이 두 문제의 정답이 모두 틀리게 나왔다. 


 

 

 

 

학습을 마치고

메서드 오버로딩에 대해 조금은 이해할 수 있는 단원이었다. 한 60% 정도 이해한 것 같다. 나머지는 복습을 하며 다음에 더 많이 알게 될 것 같다. 너무 완벽하게 학습하려고 하지 않는 편이다. 

이제 조금 쉬었다가 추상 클래스에 대해서 공부해볼 것이다.