■ 서론


다형성을 구현의 다양함 정도로 설명했고 그 예시로 오버라이딩, 오버로딩을 들었다.

다형성에 대해 좀 더 알아보고자 이렇게 정리한다.



■ 바인딩


보통은 참조변수의 타입과 객체의 타입이 일치하지만,  변수의 타입과 객체의 타입이 다른경우를 볼 수 있다.

예를들면 Map mapping = new HashMap(); 이 있다.


어떤 시점에서, 메소드가 호출될 때 어떤 코드를 수행할 것인지가 결정된다.

이러한 결정을 메소드 호출을 메소드 정의에 바인딩(binding)한다고 한다.


많은 경우에, 메소드 정의에 대한 메소드 호출의 바인딩이 컴파일 시간에 일어날 수 있다. 

그러나 다형 참조의 경우에는 실행 시간까지 바인딩을 할 수 없다.



 정적바인딩(static binding / early binding)

 동적바인딩(dynamic binding / late binding)

 private, final, static 이 이에 해당한다.


컴파일러에 의해 컴파일시간에 결정된다.

컴파일러는 객체의 타입을 알 수 없으므로,

Dog타입으로 먼저 컴파일을 진행한 후, 

실행 중 Pudle타입의 메소드가 호출된다.


런타임 중(실행시간)에 결정된다.


   class Dog {

      void sound(){

         System.out.println("멍멍~~");

      }

   }


   public static void main(String[] args) {

      Dog d = new Dog();

      d.sound();

   }

   class Pudle extends Dog { 

      void sound(){

         System.out.println("푸들~~");

      }

   }


   public class Test {

      Dog d = new Pudle();

      d.sound();

   }

 컴파일 시간에 많은 정보가 결정되므로 실행 효율이 높다.

런타임 중에 자유롭게 결정되므로 유연하다. 




■ 상속에 의한 다형성


Animal creature = new Horse(); 라고 선언하면, 변수 creature는 Animal의 어떤 객체라도 참조할 수 있다.

또한 Animal을 상속받는 어느 클래스의 객체 Horse(예시)도 참조할 수 있다.


클래스의 계층구조의 최상단에는 Object가 있는데, Object는 모든 클래스의 객체를 가르킬 수 있다는 말이된다.


Animal을 상속받은 Horse, Hippo 클래스가 있다고 하자.


Animal creature;


creature = new Horse();

creature.move(); ㅡ 1번


creature = new Hippo();

creature.move(); ㅡ 2번


이때, creature의 타입은 Animal이지만,

1번에서는 Horse의 move()가, 2번에서는 Hippo의 move()가 실행된다.


이렇게 상속에 따른 다형의 객체를 참조할 수 있으며, 

메소드 호출 또한 실행 당시의 참조 객체의 메소드를 선택하여 호출하는 것을 상속에 의한 다형성이라고 한다.




■ 인터페이스에 의한 다형성


인터페이스 역시 클래스와 마찬가지로 변수 타입으로 사용될 수 있다.


  public interface Speaker{

    
      public void speak();
      public void announce(String str);

   }

   Speaker current;

     public class Philosopher implements Speaker{

    
         public void speak(){

           System.out.println("Hello");

       }
         public void announce(String str){

           System.out.println(str);

       }

         public void Listen(){

           System.out.println("I got it");

       }


     }


라는 인터페이스와, 참조변수 current를 가정해보자.

참조변수 current는 Speaker 인터페이스를 구현하는 어떤 클래스의 객체라도 참조할 수 있다.


Philosopher 클래스가 Speaker를 implements 한다면

current = new Pilosopher(); 라고 바인딩 할 수 있다.


여기서 주의할 점은,


인터페이스 참조 변수를 사용하고 있을 때, 그 참조 변수가 가리키고 있는 객체가 

인터페이스에 없는 다른 메소드를  포함하고 있다고 할지라도, 그 인터페이스에 정의되어 있는 메소드만을 호출할 수 있다.


current는 Philosopher 타입의 객체를 바인딩 했지만 Speaker 타입이기 때문에, 

Listen()은 사용할 수 없고, Speaker 인터페이스가 가진 speak(), announce() 메소드를 사용할 수 있다.


특별한 상황에서 Listen() 메소드를 호출이 필요할 경우, 캐스팅을 사용해서 할 수도 있다.

Speaker special = new Philosopher();

((Philosopher)special).Listen();




■ 추천 사이트


예시가 아주 잘 나와있다.


https://opentutorials.org/module/516/6127




■ 출처


http://secretroute.tistory.com/entry/140819

http://blog.daum.net/_blog/BlogTypeView.do?blogid=0LoOX&articleno=6036856&_bloghome_menu=recenttext

http://hyeonstorage.tistory.com/266



'코딩 > Java 프로그래밍' 카테고리의 다른 글

OOP 용어 정리  (0) 2016.12.14
자바 Collections 클래스 Comparator  (0) 2016.11.26
[JAVA] Scanner nextInt()나 next() 사용 후 nextLine 입력  (0) 2016.11.26
자바의 4대 특성  (2) 2016.10.17

+ Recent posts