πŸ› οΈBackend/β˜•Java

[Java] λ‹€ν˜•μ„±(polymorphism)

junbin2 2025. 5. 22. 14:41

βœ… 1. λ‹€ν˜•μ„±

(1) λ‹€ν˜•μ„±μ΄λž€?

  • λ‹€ν˜•μ„±(ploymorphism)은 ν•˜μœ„ 클래슀 객체λ₯Ό μƒμ„±ν•˜κ³  μƒμœ„ 클래슀 νƒ€μž…μœΌλ‘œ λ°›λŠ” 것을 μ˜λ―Έν•œλ‹€.
  • μ‰½κ²Œλ§ν•΄, 객체λ₯Ό 생성할 λ•Œ ν•΄λ‹Ή 객체의 νƒ€μž…μœΌλ‘œ λ°›λŠ” 것이 μΌλ°˜μ μ΄λ‹€.
  • ν•˜μ§€λ§Œ, μžλ°”μ—μ„œ μ œκ³΅ν•˜λŠ” λ‹€ν˜•μ„±μ„ ν™œμš©ν•΄ ν•΄λ‹Ή 객체 νƒ€μž…μ΄ μ•„λ‹Œ, μƒμœ„ν΄λž˜μŠ€ νƒ€μž…μœΌλ‘œ λ°›μ•„μ„œ μœ μ—°ν•˜κ²Œ 이용 ν•  수 μžˆλ‹€.
  • 일반적인 방식: Dog dog = new Dog();
  • λ‹€ν˜•μ„± 적용 방식: Animal dog = new Dog(); - μƒμœ„ 클래슀둜 μ°Έμ‘° νƒ€μž…μ„ 받을 수 있음.

 

(2) λ‹€ν˜•μ„± μ“°λŠ” 이유

public class Animal {
    public void sound() {
        System.out.println("λ™λ¬Όμ†Œλ¦¬");
    }
}
public class Cat extends Animal {
    @Override
    public void sound() {
        System.out.println("고양이 μ†Œλ¦¬");
    }
}
public class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("κ°•μ•„μ§€ μ†Œλ¦¬");
    }
}
public class Main {
    public static void main(String[] args) {
        Animal cat = new Cat();
        Animal dog = new Dog();
        dog.sound(); // "κ°•μ•„μ§€ μ†Œλ¦¬" 좜λ ₯
        cat.sound(); // "고양이 μ†Œλ¦¬" 좜λ ₯
    }
}
  • μƒμœ„ν΄λž˜μŠ€ μ°Έμ‘°λ³€μˆ˜κ°€ κ°€λ¦¬ν‚€λŠ” 객체의 μ‹€μ œ μœ ν˜•μ— 따라 μˆ˜ν–‰λ˜λŠ” λ©”μ„œλ“œκ°€ 결정이 되며, 이것은 동적 λ°”μΈλ”©μ΄λΌν•œλ‹€.
  • μœ μ—°ν•¨: Animal μƒμœ„ 클래슀λ₯Ό 상속 λ°›λŠ” Dog, Cat은 Main ν΄λž˜μŠ€μ—μ„œ Animal νƒ€μž… ν•˜λ‚˜λ‘œ ν†΅μΌλ˜κ²Œ 받을 수 μžˆλ‹€.
  • μœ μ§€λ³΄μˆ˜: μƒμœ„ 클래슀 νƒ€μž…μœΌλ‘œ 받을 수 μžˆμ–΄, μ—¬λŸ¬ ν•˜μœ„ 클래슀λ₯Ό λ¬Άμ–΄μ„œ μ΄μš©ν•  μˆ˜λ„ μžˆλ‹€.

βœ… 2. λ‹€ν˜•μ„±μ˜ ν•œκ³„

// Animal: μƒμœ„ν΄λž˜μŠ€
public class Animal {
}
// Cat: ν•˜μœ„ν΄λž˜μŠ€
public class Cat extends Animal {
    public void run() {
        System.out.println("고양이 걸음");
    }
}
// Main
public class Main {
    public static void main(String[] args) {
        Animal cat = new Cat();
        cat.run(); ❌ 컴파일 μ—λŸ¬ (Animalμ—” run이 μ—†μœΌλ‹ˆκΉŒ)
    }
}
  • Animal을 μƒμ†λ°›λŠ” Cat을 new Cat()으둜 객체생성을 ν•˜κ²Œ 되면 Animal의 λͺ¨λ“  ν•„λ“œμ™€ λ©”μ„œλ“œλ₯Ό μ΄μš©ν•  수 있게 λœλ‹€.
  • 즉, Cat은 Animal을 ν¬ν•¨ν•˜κ³  μžˆμœΌλ―€λ‘œ, Animal νƒ€μž…μœΌλ‘œ Cat 객체λ₯Ό 받을 수 μžˆλ‹€λŠ” μ˜λ―Έμ΄λ‹€. ( λ‹€ν˜•μ„± )
  • ν•˜μ§€λ§Œ, λ¬Έμ œλŠ” μ½”λ“œμ—μ„œ 보면 cat.run() λ˜ν•œ Cat 객체둜 λ§Œλ“€μ—ˆκΈ° λ•Œλ¬Έμ— μ‚¬μš©μ΄ κ°€λŠ₯ν•΄μ•Ό ν•˜λŠ”λ° μ•ˆλœλ‹€.
  • μ΄μœ λŠ”, μ½”λ“œ λ¬Έλ§₯μƒμ—μ„œ λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆλ‹€κ³  νŒλ‹¨μ΄ 되기 λ•Œλ¬Έμ— 컴파일 κ³Όμ •μ—μ„œ 였λ₯˜λ₯Ό λ‚΄λ±‰λŠ” 것이닀.
  • 근데 사싀은 μ›λž˜ μ»΄νŒŒμΌλŸ¬κ°€ μ•„λ‹ˆλ©΄ JVM μƒμ—μ„œλŠ” λ¬Έμ œμ—†μ΄ 호좜이 λœλ‹€. 이것이 ν•œκ³„μ΄λ‹€.

(1) 컴파일 μ‹œμ μ—μ„œ 막아둔 이유

Animal a = new Cat();
a.run(); // ❌ 컴파일 μ—λŸ¬ (Animalμ—” run이 μ—†μœΌλ‹ˆκΉŒ)

Animal a = getRandomAnimal(); // Dog? Cat? λͺ¨λ₯΄μ§€
a.run(); // ❌ λ§Œμ•½ Dog이면 run() μ—†μ–΄μ„œ μ§„μ§œλ‘œ λŸ°νƒ€μž„ μ—λŸ¬ λ°œμƒ
  • μžλ°”λŠ” 컴파일 νƒ€μž„μ— νƒ€μž… μ•ˆμ •μ„±μ„ 맀우 μ€‘μ‹œν•œλ‹€.
  • Animal νƒ€μž…μœΌλ‘œ 뭘 받을지 λͺ¨λ₯΄λŠ” 상황과 ν•΄λ‹Ή ν΄λž˜μŠ€μ— run() λ©”μ„œλ“œκ°€ μžˆμ„μ§€ 없을지 λͺ¨λ₯΄κΈ° λ•Œλ¬Έμ— 였λ₯˜λ₯Ό λ±‰λŠ”λ‹€.
  • 즉, μ°Έμ‘° νƒ€μž…μ„ μƒμœ„ν΄λž˜μŠ€λ‘œ λ°›λŠ” 과정은 νƒ€μž…λ§Œ λ°”λ€ŒλŠ”κ±°μ§€ 아직 ν•˜μœ„ν΄λž˜μŠ€μ™€ μƒμœ„ν΄λž˜μŠ€ λͺ¨λ‘λ₯Ό κ°€μ§€κ³  μžˆλŠ” μƒνƒœμ΄λ‹€.
  • λ¬Έμ œλŠ” 컴파일 μ‹œμ μ— μœ„μ™€ 같은 λ¬Έλ§₯상 λ°œμƒν•˜λŠ” 문제λ₯Ό 막기 μœ„ν•΄ ν•˜μœ„ν΄λž˜μŠ€μ—λ§Œ μžˆλŠ” λ©”μ„œλ“œλŠ” 호좜이 λΆˆκ°€λŠ₯ν•˜κ²Œ λ§Œλ“¬

(2) 정리

  • λ‹€ν˜•μ„±μ—μ„œ ν•˜μœ„ν΄λž˜μŠ€λ§Œ κ°€μ§€κ³  μžˆλŠ” λ©”μ„œλ“œλŠ” 사싀은 호좜이 κ°€λŠ₯ν•˜μ§€λ§Œ, 컴파일 μ‹œμ μ— 막아둠
  • 컴파일 μ‹œμ μ— λ¬Έλ§₯상 μ•ˆμ „ν•˜μ§€ μ•Šλ‹€λŠ” 이유둜 막아둔 κ²ƒμž„.
  • 즉, ν•˜μœ„ 클래슀만 κ°€μ§„ λ©”μ„œλ“œλŠ” μ°Έμ‘° λ³€μˆ˜λ₯Ό ν•˜μœ„ 클래슀 νƒ€μž…μœΌλ‘œ λ°”κΏ”μ•Ό 호좜이 κ°€λŠ₯ν•˜λ‹€λŠ” μ˜λ―Έμž„. ( μ—…/λ‹€μš΄ μΊμŠ€νŒ… )
  • μ˜€λ²„λΌμ΄λ”©λœ λ©”μ„œλ“œλŠ” κ°€λŠ₯함. μ΄μœ λŠ”, μƒμœ„ν΄λž˜μŠ€μ— μ •μ˜κ°€ λ˜μ–΄μžˆλ‹€λŠ” ν•„μˆ˜μ μΈ κ·œμΉ™μ΄ μ‘΄μž¬ν•˜κΈ° λ•Œλ¬Έ

(3) 두 쀄 정리

  • κ°μ²΄λŠ” “λ‚΄κ°€ μ†ν•œ ν΄λž˜μŠ€ + λΆ€λͺ¨ ν΄λž˜μŠ€”의 λͺ¨λ“  μ •보λ₯Ό κ°€μ§€κ³  μžˆκ³ , λ‹€ν˜•성은 μ»΄νŒŒμΌ μ‹œμ μ— ‘μ•ˆμ „ν•œ ν˜ΈμΆœ’을 μœ„ν•΄ λΆ€λͺ¨ νƒ€μž…μœΌλ‘œ μ œν•œν•˜μ§€λ§Œ, λŸ°νƒ€μž„μ—λŠ” μ‹€μ œ κ°μ²΄ λ©”μ„œλ“œλ₯Ό μ‹€ν–‰ν•œλ‹€λŠ” κ²ƒ!
  • λ‹€ν˜•μ„±μ€ μ§„μ§œμ§„μ§œ λ‹¨μˆœνžˆ μ½”λ“œμ˜ μœ μ—°μ„±κ³Ό μœ μ§€λ³΄μˆ˜ λ•Œλ¬Έμ— λ§Œλ“€μ–΄μ‘Œμ§€λ§Œ, λ¬Έμ œλŠ” μžλ°” λ¬Έλ§₯ κ΅¬μ‘°μƒμ˜ ν•œκ³„λ‘œ μ œν•œμ„ λ‘κ²Œ 된 것이며, 이 λ•Œλ¬Έμ— λ‹€ν˜•μ„±μ΄ μ–΄λ ΅κ²Œ λŠκ»΄μ§„ 것 이라고 생각이 λ“ λ‹€.

μžλ°” λ©”μ„œλ“œ 호좜 원리

  • Heap에 μƒμ„±λœ 객체 μΈμŠ€ν„΄μŠ€λŠ” ν•„λ“œ(μΈμŠ€ν„΄μŠ€ λ³€μˆ˜) λ°μ΄ν„°λ§Œ κ°€μ§€κ³  있고, λ©”μ„œλ“œλŠ” κ°€μ§€κ³  μžˆμ§€ μ•ŠλŠ”λ‹€.
  • μ‹€μ œ λ©”μ„œλ“œλŠ” MethodArea(클래슀 μ˜μ—­)에 λ“€μ–΄κ°€ μžˆλŠ” 정보에 λ©”μ„œλ“œ μ½”λ“œμ˜ μœ„μΉ˜λ₯Ό μ°Έμ‘°ν•˜κ²Œ λœλ‹€.
  • 즉, Heap λ‚΄λΆ€μ—λŠ” MethodArea의 λ©”μ„œλ“œλ₯Ό μ°Έμ‘°κ°’λ§Œμ„ κ°€μ§€κ³  μžˆλŠ” 것이닀.