Langauge/Java-basic

[Java] 메서드 오버라이딩(Method Overriding)

강잇 2022. 7. 31. 20:40

메서드 오버라이딩이란

메서드 오버라이딩(Method Overriding)상위 클래스로부터 상속받은 메서드와 동일한 이름의 메서드를 재정의하는 것

출처 : MBC

메서드 오버라이딩을 학습하며 가장 떠오른 짤.. "이 메서드는 이제 제 겁니다. 제 마음대로 할 수 있는 것입니다."같은 느낌..

class Animal {
    public void cry() {
        System.out.println("울음소리");
    }
}
class Cat extends Animal {
    @Override
    public void cry() { // 상위 클래스의 cry() 오버라이딩
        System.out.println("냐옹~");
    }
}
class Dog extends Animal {
    @Override
    public void cry() { // 상위 클래스의 cry() 오버라이딩
        System.out.println("멍멍!");
    }
}

메서드 오버라이딩 조건

  • 상위 클래스의 메서드와 시그니처 및 리턴 타입이 동일해야 한다.
  • 접근 제어자의 범위가 상위 클래스의 메서드보다 같거나 넓어야 한다.
    하위 클래스 접근 제어자 범위 >= 상위 클래스 접근 제어자 범위
  • 예외는 상위 클래스의 메서드보다 많이 선언할 수 없다.

메서드 오버라이딩 메모리 구조

  1. 하위 클래스의 인스턴스를 생성하면 먼저 힙 메모리에 상위 클래스의 인스턴스가 생성
  2. 상위 클래스의 인스턴스 내부의 메서드는 인스턴스 메서드 영역에 생성
  3. 하위 클래스의 인스턴스가 상위 클래스를 포함하는 구조로 생성
  4. 하위 클래스 내부의 메서드도 동일하게 인스턴스 메서드 영역에 생성
  5. 이때 오버라이딩한 메서드는 기존에 있던 메서드를 덮어씀
  6. 상위 클래스의 인스턴스도 하위 클래스의 인스턴스도 동일한 메서드를 가리키고 있기 때문에 어떠한 타입으로 메서드를 호출해도 오버라이딩 된 메서드가 호출됨.
  7. 폴더 덮어쓰기예시로 생각하면 쉽게 이해 가능

메서드 오버라이딩 사용 이유

  • 메서드 오버라이딩의 특성을 이용하여 다형성을 더욱 증가시킬 수 있다.(코린이의 개인적인 생각)
    메서드 오버라이딩을 할 수 없으면 하위 클래스에서 일일이 정의를 해야 하며 상위 클래스의 타입으로 인스턴스를 생성하게 되면 다운 캐스팅을 하지 않고는 당연히 하위 클래스에서 정의한 기능을 사용할 수 없기 때문에..
  • 다형적 표현을 사용하여 모든 객체를 상위 클래스 타입으로 선언하여 배열로 관리할 수 있다.
public class Main {
    public static void main(String[] args) {
        // 각각의 타입으로 선언 및 인스턴스 생성
        Cat cat1 = new Cat();
        Dog dog1 = new Dog();
        Wolf wolf1 = new Wolf();

        cat1.cry();
        dog1.cry();
        wolf1.cry();

        // 상위 클래스 타입 + 하위 클래스 생성자
        Animal cat2 = new Cat();
        Animal dog2 = new Dog();
        Animal wolf2 = new Wolf();

        cat2.cry();
        dog2.cry();
        wolf2.cry();

        // 다형적 표현을 이용한 배열로 묶어 호출
        Animal[] animals = new Animal[]{new Cat(), new Dog(), new Wolf()};
        for (Animal animal : animals) {
            animal.cry();
        }
    }
}
class Animal {
    public void cry() {} // 오버라이딩을 하기 위해 정의한 메서드로 내용 생략 가능
}
class Cat extends Animal {
    @Override
    public void cry() { // Animal의 cry() 오버라이딩
        System.out.println("냐옹~");
    }
}
class Dog extends Animal {
    @Override
    public void cry() { // Animal의 cry() 오버라이딩
        System.out.println("멍멍!");
    }
}
class Wolf extends Animal {
    @Override
    public void cry() { // Animal의 cry() 오버라이딩
        System.out.println("아오오~~~");
    }
}

출력 결과