본문 바로가기
개발공부/Java

[Java] 16. 메서드 재정의(Overriding)와 가상 메서드 원리

by sangyeon 2022. 1. 24.
728x90

1. 하위 클래스에서 메서드 재정의하기

  • 오버라이딩(overriding): 상위 클래스에 정의된 메서드의 구현 내용이 하위 클래스에서 구현할 내용과 맞지 않는 경우 하위 클래스에서 동일한 이름의 메서드를 정의하여 사용하는 것.
  • VIPCustomer 클래스의 calcPrice()는 할인율이 적용되지 않기 때문에 재정의하여 구현해야 함.

- VIPCustomer.java

@Override
public int calcPrice(int price) {
             
              bonusPoint += price * bonusRatio;
              return price - (int)(price * salesRatio);

}

> 하위 클래스에서 calcPrice라는 메서드를 재정의한다. *가격에 대한 할인율이 들어간다.

> VIPCustomer.java 에서 화면에서 우클릭 > Source > Override/Implement method.. 선택 후 오버라이드 가능한 메서드를 선택한다.

 

2. overriding 어노테이션(annotation)

  • 어노테이션은 원래 주석이라는 의미.
  • 컴파일러에게 특별한 정보를 제공해주는 역할
  • @overriding 어노테이션은 재정의된 메서드라는 의미로 선언부가 기존의 메서드와 다른 경우 에러가 난다.

이미지 출처 - https://gitlab.com/easyspubjava/javacoursework/-/blob/master/Chapter3/3-04/README.md

 

 

3. 형 변환과 오버라이딩 메서드 호출

  • Customer vc = new VIPCustomer();
  • vc 변수의 타입은 Customer이지만 인스턴스 타입은 VIPCustomer이다.
  • 자바에서는 항상 인스턴스의 메서드가 호출되기 때문에 자바의 모든 메서드는 가상 메서드이다.

- CustomerTest.java

package ch04;

public class CustomerTest {

public static void main(String[] args) {

int price = 0;

Customer customerLee = new Customer(10010, "이순신");
customerLee.bonusPoint = 1000;
price = customerLee.calcPrice(1000);
System.out.println(customerLee.showCustomerInfo() + 
"\n 1000원짜리 제품의 가격은 " + price + "원 입니다");

System.out.println();

VIPCustomer customerKim = new VIPCustomer(10020, "김유신");
customerKim.bonusPoint = 10000;
price = customerKim.calcPrice(1000);
System.out.println(customerKim.showCustomerInfo() + 
"\n 1000원짜리 제품의 가격은 " + price + "원 입니다.");


// 그렇다면 VIPCustomer로 생성했는데 Customer형으로 변환한 vc의 경우에는?
Customer vc = new VIPCustomer(12345, "noname");
price = vc.calcPrice(1000);
System.out.println(price);

// 900이 출력됨. 이게 가상함수 방식이다. (이것이 가상 메서드..)
// VIPCustomer의 실제 인스턴스의 메서드가 호출이 된다.
}
}

출력값 ..

이순신님의 등급은 SILVER이며, 보너스 포인트는 1010입니다.
 1000원짜리 제품의 가격은 1000원 입니다

김유신님의 등급은 VIP이며, 보너스 포인트는 10050입니다.
 1000원짜리 제품의 가격은 900원 입니다.

vc 값 출력 : 900

 

4. 메서드(함수)는 어떻게 호출되고 실행 되는가?

  • 메서드(함수)의 이름은 주소값을 나타낸다.
  • 메서드는 명령어의 set이고 프로그램이 로드되면 메서드 영역(코드 영역)에 명령어 set이 위치한다.
  • 해당 메서드가 호출되면 명령어 set이 있는 주소를 찾아 명령어가 실행된다.
  • 이때 메서드에서 사용하는 변수들은 스택 메모리에 위치하게 된다.
  • 따라서 다른 인스턴스라도 같은 메서드의 코드는 같으므로 같은 메서드가 호출된다.
  • 인스턴스가 생성되면 변수는 힙 메모리에 따로 생성되지만, 메서드 명령어 set은 처음 한번만 로드 된다.
public class TestMethod {

    int num;

    void aaa() {
       System.out.println("aaa() 호출");
    }

     public static void main(String[] args) {

        TestMethod a1 = new TestMethod();
        a1.aaa();

        TestMethod a2 = new TestMethod();
        a2.aaa();
   }

}

- aaa라는 메서드는 출력문을 실행하는 것

- main 함수의 a1, a2, args는 지역변수이고

- 객체(인스턴스)가 생성된 a1, a2는 힙 메모리에 올라간다.

- aaa() 메서드에서 사용하는 지역변수는 다시 스택 메모리에 올라간다. (예제에선 지역변수가 없지만..)

출처 - https://gitlab.com/easyspubjava/javacoursework/-/blob/master/Chapter3/3-05/README.md

 

5. 가상 메서드의 원리

  • 가상 메서드 테이블에서 해당 메서드에 대한 주소를 가지고 있다.
  • 재정의된 경우는 재정의된 메서드의 주소를 가리킨다.

출처 - https://gitlab.com/easyspubjava/javacoursework/-/blob/master/Chapter3/3-05/README.md

- showCustomerInfo의 경우 재정의되지 않았기 때문에 동일한 메서드 주소 값을 갖고,

- override된 calcPrice 메서드의 경우에는 각각의 메서드 주소를 갖는다. 

 

 

1. 상속

2. 형 변환 (상위 클래스로 형이 대입된다.)

3. 재정의(Override - 상위 클래스에 있는 메서드를 재정의해서 입맛 대로 바꿈)

4. 인스턴스에서 재정의된 메서드가 호출된다.

 

728x90