BACKEND/JAVA

상속과 메서드 오버라이딩, 가상 메서드 원리

우진하다 2023. 6. 8. 22:03

 

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

오버라이딩.
상위 클래스에 정의된 메서드의 구현 내용이 하위 클래스에서 구현할 내용과 맞지 않을 때
하위 클래스에서 동일한 이름의 메서드를 재정의 할 수 있다.
@overriding 애노테이션을 붙이면 재정의 된 메서드라는 의미로 선언부가 기존의 메서드와 다른 경우 에러가 난다.

class Animal {
    public void sound() {
        System.out.println("동물이 소리를 낸다.");
    }
}

class Cat extends Animal {
    @Override
    public void sound() {
        System.out.println("야옹~");
    }
}

class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("멍멍!");
    }
}

public class Main08Test {
    public static void main(String[] args) {
        Animal animal = new Animal();
        animal.sound(); // "동물이 소리를 낸다."

        Cat cat = new Cat();
        cat.sound(); // "야옹~"

        Dog dog = new Dog();
        dog.sound(); // "멍멍!"
    }
}

 

묵시적 클래스 형 변환과 메서드 재정의

만약 타입은 Aniaml 이고 인스턴스는 Dog 일 때는 어떤 메서드가 실행될지 생각해봅시다.
이전에 변수는 상위 클래스만 접근할 수 있었는데 출력 결과를 보면 Dog 에서 재정의된 메서드가 호출 되는걸 확인할 수 있다.

        Animal animal1 = new Dog();
        animal1.sound(); // "멍멍!"

상속에서 상위 클래스와 하위 클래스에 같은 이름의 메서드가 존재할 때 호출되는 메서드는 인스턴스에 따라 결정된다.
인스턴스 메서드가 호출되는 것을 가상 메서드라고 한다.
자바에서는 항상 인스턴스의 메서드가 호출 됨 (가상메서드의 원리)
자바의 모든 메서드는 가상 메서드(virtual method) 임

메서드 재정의와 가상 메서드 원리.

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

자바의 클래스는 멤버 변수와 메서드로 구성된다.
클래스를 생성하여 인스턴스가 만들어지면 멤버 변수는 인스턴스가 생성될 때마다 새로이 힙 메모리에 위치한다.
하지만 메서드는 실행해야 할 명령 집합이기 때문에 인스턴스가 달라도 같은 로직을 수행한다.
즉, 같은 객체의 인스턴스를 여러 개 생성한다고 해서 메서드도 여러개 생성되지 않는다.

public class Test {
    int num;

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

    public static void main(String[] args) {
        Test a1 = new Test();
        a1.aaa();

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

 

가상 메서드의 원리.

- 가상 메서드 테이블(vitual method table)에서 해당 메서드에 대한 address를 가지고 있음
- 재정의된 경우는 재정의 된 메서드의 주소를 가리킴

상위 클래스에서 선언한 메서드가 있고 
이를 하위 클래스에서 재정의한 상태에서 하위클래스 인스턴스가 상위 클래스로 형변환이 되면
생성된 클래스의 인스턴의 메서드가 호출된다.