다형성(Polymorphism )

<aside> 💡

다형성은 사용 방법은 동일하지만 다양한 객체를 이용해서 다양한 실행결과가 나오도록 하는 성질입니다.

</aside>

// 부모 클래스
class Animal {
    protected String name;
    
    public Animal(String name) {
        this.name = name;
    }
    
    public void sound() {
        System.out.println("동물이 소리를 냅니다.");
    }
}

// 자식 클래스
class Dog extends Animal {
    private int age;
    
    public Dog(String name, int age) {
        super(name);
        this.age = age;
    }
    
    @Override
    public void sound() {
        System.out.println("멍멍!");
    }
}

public class Main {
    public static void main(String[] args) {
        // 다형성을 활용한 객체 생성
        Animal animal = new Dog("바둑이", 3);
        animal.sound(); // "멍멍!" 출력
    }
}

메모리 형성과정

graph TD
    subgraph 메소드영역_Method_Area
        AnimalClass["Animal 클래스 바이트코드<br/>---------------<br/>+sound() {...}"]
        DogClass["Dog 클래스 바이트코드<br/>---------------<br/>+sound() {...}"]
        DogClass -->|상속| AnimalClass
    end
    
    subgraph 힙_Heap
        DogInstance["Dog 인스턴스<br/>---------------<br/>name='바둑이'<br/>age=3"]
        DogMetadata["Dog 클래스 메타데이터<br/>---------------<br/>- 메소드 테이블<br/>  sound() -> Dog.sound()<br/>- 필드 정보<br/>  name: String<br/>  age: int"]
        AnimalMetadata["Animal 클래스 메타데이터<br/>---------------<br/>- 메소드 테이블<br/>  sound() -> Animal.sound()<br/>- 필드 정보<br/>  name: String"]
    end
    
    subgraph 스택_Stack
        animal["animal<br/>(Animal 타입 참조변수)"]
    end
    
    DogMetadata -->|상속 메타데이터| AnimalMetadata
    DogInstance -->|클래스 정보 참조| DogMetadata
    DogMetadata -->|메소드 참조| DogClass
    AnimalMetadata -->|메소드 참조| AnimalClass
    animal -->|참조| DogInstance

<aside> 💡

  1. 메소드 영역 (Method Area):
  2. 힙 영역 (Heap):
  3. 참조 관계:

이렇게 구성되면 메소드 호출 시:

  1. 참조변수로부터 인스턴스 접근
  2. 인스턴스에서 클래스 메타데이터 접근
  3. 메타데이터의 메소드 테이블을 통해 실제 구현부 찾기
  4. 메소드 영역의 해당 바이트코드 실행 </aside>

super가 힙 메모리에 독립적으로 없는가?

한 객체에 포함되는 이유

오버라이드의 동작 원리

  1. Method Area에 저장되는 메서드 정보:
    • SuperclassSubclass는 각각 superMethod()의 바이트코드 위치를 정의합니다.
    • Subclass에서 superMethod()를 오버라이드했으므로, Subclass 메타데이터가 오버라이드된 메서드의 바이트코드 위치를 가리킵니다.
  2. Heap Memory의 객체:
    • 힙 메모리의 Subclass 객체는 여전히 superFieldsubField를 포함합니다.
    • 참조 변수(obj)의 타입에 상관없이, 실제 객체의 클래스(Subclass)에 정의된 메서드가 호출됩니다.
  3. Stack Memory의 메서드 호출:
    • obj.superMethod() 호출 시, 실제 객체의 클래스(Subclass)의 메서드를 실행합니다.
    • 이는 실행 시점에 메서드가 동적으로 바인딩되기 때문입니다 (Dynamic Method Dispatch).

왜 오버라이드된 메서드가 호출되는가?