Polymorphism

Java 의 Polymorphism (λ‹€ν˜•μ„±) 은 ν•˜λ‚˜μ˜ 객체λ₯Ό μ—¬λŸ¬ νƒ€μž…μœΌλ‘œ λ‚˜νƒ€λ‚΄κ²Œ ν•˜μ—¬ λ‹€μ–‘ν•œ κΈ°λŠ₯으둜 μ΄μš©ν•  수 μžˆλ„λ‘ ν•˜λŠ”κ²ƒμ΄λ‹€.

μ΄λŠ” μ½”λ“œμ˜ μœ μ—°ν•˜λ©° μž¬μ‚¬μš©μ΄ κ°€λŠ₯ν•˜λ„λ‘ κ΅¬ν˜„λ˜λ©° 크게 Dispatch 방법에 따라 Static Dispatch 와 Dynamic Dispatch 둜 λ‚˜λ‰œλ‹€.

Dispatch

ν”„λ‘œκ·Έλž¨μ΄ μ–΄λ–€ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•  것인가λ₯Ό κ²°μ •ν•˜μ—¬ 그것을 μ‹€ν–‰ν•˜λŠ” 과정을 λ§ν•œλ‹€.

Static Dispatch

Static Dispatch λŠ” ν”„λ‘œκ·Έλž¨μ΄ 컴파일 μ‹œμ μ— μ•Œμˆ˜ 있으며 λŒ€ν‘œμ μœΌλ‘œ Method Overloading 이 μžˆλ‹€.

Method Overloading (λ©”μ„œλ“œ μ˜€λ²„λ‘œλ”©)

같은 μ΄λ¦„μ˜ λ©”μ„œλ“œλ₯Ό μ—¬λŸ¬κ°œ μ •μ˜ν•˜κ³  λ§€κ°œλ³€μˆ˜μ˜ μœ ν˜•κ³Ό 개수λ₯Ό λ‹€λ₯΄κ²Œ ν•˜μ—¬ λ‹€μ–‘ν•œ μœ ν˜•μ˜ ν˜ΈμΆœμ— μ‘λ‹΅ν•˜λŠ” 방법이닀.

μ΄λŠ” Function Signature λ₯Ό λ‹€λ₯΄κ²Œ ν•˜μ—¬ μ‚¬μš©ν•˜λŠ” 방법 으둜 Method Signature κ°€ λ™μΌν•˜λ©΄ μ‚¬μš©μ΄ λΆˆκ°€ν•˜λ‹€.




Β 








Β 



public class Dispatch {
  static class Service {
    void run() {
      System.out.println("run");
    }

    void run(String msg) {
      System.out.println(msg);
    }
  }

  public static void main(String[] args) {
    new Service().run();
  }
}

μœ„ μ½”λ“œμ˜ main() λ©”μ„œλ“œλ₯Ό μ‹€ν–‰ν•˜κ²Œ 되면 Service 클래슀의 run() λ©”μ„œλ“œμ€‘ μ–΄λŠκ²ƒμ΄ μ‹€ν–‰λ˜λŠ”μ§€λŠ” λŸ°νƒ€μž„μ΄ μ•„λ‹Œ 컴파일 μ‹œμ μ— μ•Œ 수 μžˆλ‹€.

컴파일 μ‹œμ μ— μ•Œ 수 μžˆμœΌλ―€λ‘œ μ–΄λ–€ λ©”μ„œλ“œκ°€ ν˜ΈμΆœλ μ§€λŠ” 컴파일이 μ’…λ£Œλœ ν›„ λ°”μ΄νŠΈ μ½”λ“œμ—λ„ λ“œλŸ¬λ‚˜κ²Œ λ˜μ–΄ μžˆλ‹€.

Dynamic Dispatch

νŠΉμ • λ©”μ„œλ“œλ‚˜ ν•¨μˆ˜ κ΅¬ν˜„μ΄ ν”„λ‘œκ·Έλž¨μ˜ λŸ°νƒ€μž„μ— κ²°μ •λ˜λŠ” κ²ƒμœΌλ‘œ λŒ€ν‘œμ μœΌλ‘œλŠ” Method Overriding 이 μžˆλ‹€.

정적 λ””μŠ€νŒ¨μΉ˜ (static dispatch) 에 λΉ„ν•΄μ„œλŠ” 느리고 컴파일러의 μ΅œμ ν™”λ₯Ό 막아 λΉ„μš©μ΄ 더 크게 λ°œμƒλ  수 μžˆλ‹€.

Method Overriding (λ©”μ„œλ“œ μ˜€λ²„λΌμ΄λ”©)

μƒμœ„ ν΄λž˜μŠ€κ°€ 가지고 μžˆλŠ” λ©”μ†Œλ“œλ₯Ό ν•˜μœ„ ν΄λž˜μŠ€κ°€ 재 μ •μ˜ ν•˜μ—¬ μ‚¬μš©ν•˜λŠ” 것

public class Dispatch {
  static abstract class Service {
    abstract void run();
  }

  static class MyServcie1 extends Service {
    @Overried
    void run() {
      System.out.println("MyService 1");
     }
  }

  static class MyService2 extends Service {
    @Overried
    void run() {
      System.out.println("MyService 2");
     }
  }

  public static void main(String[] args) {
    Service svc = new MyService1();
    svc.run()
  }
}

μœ„ μ½”λ“œμ˜ μ–΄λ–€ 클래슀의 run() λ©”μ„œλ“œκ°€ μ‹€ν–‰λ μ§€λŠ” 컴파일 μ‹œμ μ—λŠ” μ•Œ 수 μ—†λ‹€.

λ‹€μ΄λ‚˜λ―Ή λ””μŠ€νŒ¨μΉ­μ€ λ¦¬μ‹œλ²„ νŒŒλΌλ©”ν„°μ— μ˜ν•œ λ©”μ†Œλ“œ ν˜ΈμΆœμ„ μ‚¬μš©ν•˜λŠ” 객체 λ³€μˆ˜μ— μ˜ν•΄ κ²°μ • λ˜λŠ”κ²ƒμœΌλ‘œ νŒŒλΌλ©”ν„° νƒ€μž…μ— μ˜ν•΄ κ²°μ •λ˜λŠ” 것이 μ•„λ‹ˆλ‹€.

Method Signature (λ©”μ„œλ“œ μ‹œκ·Έλ‹ˆμ²˜)

λ©”μ„œλ“œμ˜ 이름 (Method Name) κ³Ό λ§€κ°œλ³€μˆ˜μ˜ νƒ€μž… (Parameter Types) 이 κ°™μœΌλ©΄ λ©”μ„œλ“œ μ‹œκ·Έλ‹ˆμ²˜κ°€ κ°™λ‹€κ³  ν•œλ‹€.

WARNING

λ°˜ν™˜κ°’μ˜ νƒ€μž… (Return Type) 은 λ©”μ„œλ“œ μ‹œκ·Έλ‹ˆμ²˜μ— ν¬ν•¨λ˜μ§€ μ•ŠλŠ”λ‹€.

Function Signature (ν•¨μˆ˜ μ‹œκ·Έλ‹ˆμ²˜)

ν•¨μˆ˜μ˜ μ›ν˜•μ— λͺ…μ‹œλ˜λŠ” λ§€κ°œλ³€μˆ˜μ˜ 리슀트λ₯Ό κ°€λ₯΄ν‚¨λ‹€.
두 ν•¨μˆ˜μ˜ λ§€κ°œλ³€μˆ˜μ˜ 갯수 와 νƒ€μž… 이 κ°™μœΌλ©΄ 두 ν•¨μˆ˜μ˜ μ‹œκ·Έλ‹ˆμ²˜λŠ” κ°™λ‹€κ³  ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

int sum (int a, int b, double c);

int sum2 (int, int, double);

μœ„ 두 ν•¨μˆ˜μ˜ μ‹œκ·Έλ‹ˆμ²˜κ°€ κ°™λ‹€.
μ‹œκ·Έλ‹ˆμ²˜κ°€ 같은 ν•¨μˆ˜λŠ” 같은 ν•¨μˆ˜ 포인터에 μ˜ν•΄ μƒν˜Έν˜Έν™˜μ΄ κ°€λŠ₯ν•˜λ‹€.

Double Dispatch

μ‹±κΈ€ λ””μŠ€νŒ¨μΉ­μ΄ μ—¬λŸ¬λ²ˆ μΌμ–΄λ‚˜λŠ” 것이 더블 λ””μŠ€νŒ¨μΉ­μ΄λ‹€.

interface Game {
  void play(Play play);
}

static class Init implements Game{
  @Override
  public void play(Play play) {
    play.run(this);
  }
}

static class Score implements Game {
  @Override
  public void play(Play play) {
    play.run(this);
  }
}

interface Play {
  void run(Init init);
  void run(Score score);
}

static class Puzzle implements Play {
  @Override
  public void run(Init init) {
    System.out.println("Init Puzzle");
  }

  @Override
  public void run(Score score) {
    System.out.println("Score Puzzle");
  }
}

static class Action implements Play {
  @Override
  public void run(Init init) {
    System.out.println("Init Action");
  }

  @Override
  public void run(Score score) {
    System.out.println("Score Action");
  }
}

@Test
public void doubleDispatch() {
  List<Game> games = Arrays.asList(new Init(), new Score());
  List<Play> play = Arrays.asList(new Puzzle(), new Action());

  games.forEach(g -> play.forEach(p -> g.play(p)));
}