본문 바로가기
JAVA/객체지향

자바 메소드 재정의 의미, 사용방법 (@Override)

by 스코리아 2023. 8. 31.

안녕하세요, 스코리아입니다.

오늘은 자바 메소드 재정의(Overridng)의 의미와 사용방법에 대해서 알아보도록 하겠습니다.

[이전 내용 참고] 오버로딩 vs 오버라이딩 : 생성자 오버로딩은 무엇인가? : https://skorea6.tistory.com/7

 

메소드 재정의 (Method Overriding)란?

  • 상위 클래스에 정의된 메서드의 구현 내용이 하위 클래스에서 구현할 내용과 맞지 않는 경우, 하위 클래스에서 동일한 이름의 메서드를 재정의 할 수 있음
  • 하위 클래스에서 상위 클래스의 동일한 메소드 이름으로 메소드를 다시 정의하는 것을 의미

 

@Override 애노테이션

  • 애노테이션은 원래 주석이라는 의미
  • 컴파일러에 특정 정보를 주는 역할
  • @Override 애노테이션은 "재정의 된 메서드"라는 의미로 선언부가 기존의 메서드와 다른 경우 에러가 남
애노테이션 설명
@Override 재정의된 메소드라는 정보 제공
@FunctionalInterface 함수형 인터페이스라는 정보 제공
@Deprecated 이후 버전에서는 사용되지 않을 변수, 메소드에 사용됨
@SupressWarnings 특정 경고가 나타나지 않도록함
(예) @SupressWarnings("deprecation")는 @Deprecated가 나타나지 않도록 함

 

메소드 재정의 예시

이전 시간에 예시로 만들었던 Customer와 VIPCustomer 클래스를 활용하여 메소드 재정의 예시에 대해서 설명하겠습니다.

이전 "자바의 상속" 내용 참고하기 : https://skorea6.tistory.com/21

 

우선 상위 클래스인 Customer 클래스를 만들기 위해 Customer.java 파일을 만들어봅시다.

public class Customer {
    protected int customerID;
    protected String customerName;
    protected String customerGrade;
    int bonusPoint;
    double bonusRatio;

    public Customer(int customerID, String customerName) {
        this.customerID = customerID;
        this.customerName = customerName;

        customerGrade = "SILVER";
        bonusRatio = 0.01;
    }

    public int calcPrice(int price) {
        bonusPoint += price * bonusRatio;
        return price;
    }

    public String showCustomerInfo() {
        return customerName + "님의 등급은 " + customerGrade + "이며, 보너스 포인트는" + bonusPoint + "입니다";
    }
}

이제 하위 클래스인 VIPCustomer 클래스를 만들기 위해 VIPCustomer.class 파일을 만들어봅시다.

public class VIPCustomer extends Customer {
    private int agentID;
    double salesRatio;

    public VIPCustomer(int customerID, String customerName) {
        super(customerID, customerName);
        customerGrade = "VIP";
        bonusRatio = 0.05;
        salesRatio = 0.1;
    }

    /**
     - 메소드 오버라이딩 (overriding)
     */
    @Override
    public int calcPrice(int price) {
        bonusPoint += price * bonusRatio;
        return price - (int)(price * salesRatio);
    }

    public int getAgentID() {
        return agentID;
    }

    @Override
    public String showCustomerInfo() {
        return super.showCustomerInfo() + " 상담원 아이디는 " + agentID;
    }
}
  • 상위 클래스의 메소드인 calcPrice와 showCustomerInfo를 하위 클래스인 VIPCustomer에서 메소드를 재정의하였습니다.
  • 하위 클래스에서 재정의할 메소드를 만들어주는 인텔리제이 단축키는 cmd + O입니다.
  • 상위 클래스에 정의된 메소드의 구현 내용이 하위 클래스의 구현 내용과 맞지 않은 경우 하위 클래스에서 동일한 이름의 메소드로 재정의할 수 있습니다.
  • 재정의한 메서드 위에 '@Override' 어노테이션을 붙여서 기존의 메소드와 선언부가 다를 경우, 컴파일러상에서 오류가 날 수 있게끔 합니다. 예를 들면, calcPrice 메소드에서  int price를 double price로 바꾸면 오류가 생기게끔 해줍니다. 즉, 선언부가 기존의 메서드와 다른 경우 에러가 납니다.

이제 상위 클래스인 Customer 클래스와 하위 클래스인 VIPCustomer 클래스를 이용해서 오버라이딩된 메소드를 테스트해 보도록 하겠습니다. CustomerTest.java 파일을 만들어봅시다.

public class CustomerTest {
    public static void main(String[] args) {
        int price = 10000;

        Customer customerLee = new Customer(10010, "이순신");
        customerLee.bonusPoint = 1000;
        int cost = customerLee.calcPrice(price);
        System.out.println(customerLee.showCustomerInfo() + " 지불 금액은 " + cost + "입니다.");

        VIPCustomer customerKim = new VIPCustomer(10020, "김유신");
        customerKim.bonusPoint = 10000;
        cost = customerKim.calcPrice(price);
        System.out.println(customerKim.showCustomerInfo() + " 지불 금액은 " + cost + "입니다.");

        Customer customerPark = new VIPCustomer(10021, "Park");
        customerPark.bonusPoint = 10000;
        cost = customerPark.calcPrice(price);
        System.out.println(customerPark.showCustomerInfo() + " 지불 금액은 " + cost + "입니다.");
    }
}
  • customerLee 이름을 가진 Customer 인스턴스를 생성한 후, calcPrice 메소드를 호출하였습니다. 이때는 Customer 클래스에 작성된 calcPrice 메소드가 호출됩니다. showCustomerInfo 메소드도 마찬가지입니다.
  • customerKim 이름을 가진 VIPCustomer 인스턴스를 생성한 후, calcPrice 메소드를 호출하였습니다. 이때는 VIPCustomer 클래스에 재정의(오버라이딩)된 메소드가 호출됩니다. showCustomerInfo 메소드도 마찬가지입니다.

  • 하위 클래스인 VIPCustomer에서 상위 클래스인 Customer로 자동타입변환을 하였습니다. customerPark 변수 타입은 Customer이지만 인스턴스의 타입은 VIPCustomer입니다.
  • 자동타입변환된 customerPark를 이용해 calcPrice 메소드를 호출하면, 하위 클래스인 VIPCustomer의 오버라이딩된 것이 호출됩니다.
  • 즉, 자바의 가상 메소드의 원리에 따라 자바에서는 항상 인스턴스의 메소드가 호출이 일어납니다

메소드 재정의 예시 - 실행결과

customerPark.getAgentId();
  • getAgentId() 메소드는 부모클래스인 Customer에 정의되어있지 않고 자식 클래스인 VIPCustomer에만 정의되어 있으므로, 자동타입변환된 customerPark를 이용하여 메소드를 호출할 수 없습니다.

 

가상 메소드의 원리 (Virtual Method Table)

자바의 가상 메소드 원리 (메소드 오버라이딩)
자바의 가상 메소드 원리 (메소드 오버라이딩)

  • 위 그림과 같이 가상 메서드 테이블에서 해당 메서드에 대한 주소(address)를 가지고 있습니다
  • 재정의된 경우에는 재정의된 메소드의 주소를 가리킵니다.

 


이렇게 지금까지 자바(Java)의 메소드 오버라이딩의 의미, 사용 방법에 대해서 알아보았습니다.

읽어주셔서, 감사합니다.