[Java-OOP7] 다형성

이용준·2022년 11월 1일
0

Java

목록 보기
19/29

객체지향 프로그래밍의 특징 중에는 다형성(폴리모피즘, Polymorphism)이 있다. 이는 무엇이고 왜 필요한지 예제를 통해 알아보도록 한다.

  • 예제
interfaec Predator{
  (...)
}

class Animal{
  (...)
}
class Tiger extends Animal implements Predator{
  (...)
}
class Lion extends Animal implements Predator{
  (...)
}

class ZooKeeper{
 (...)
}

//추가
class Bouncer{
  void barkAnimal(Animal animal){
    if (animal instanceof Tiger){
      System.out.println("어흥");
    }else if(animal instanceof Lion){
      System.out.println("으르렁");
    }
  }
}

public class Sample{
  public static void main(String[] args){
    Tiger tiger = new Tiger();
    Lion lion = new Lion();
    
    //추가
    Boucer bouncer = new Bouncer();
    bouncer.barkAnimal(tiger);  // 호랑이는 어흥
    bouncer.barkAnimal(lion);  // 사자는 으르렁
  }
}  

경비원Bouncer 클래스는 동물을 짖게(barkAnimal)해 건물을 지킨다 한다.

  • instacneof

    • 어떤 객체가 특정 클래스의 객체인지 객체 타입을 확인하는 연산자
    • 형변환 가능 여부를 확인하며 true/false로 결과를 반환한다.
    • 주로 상속관계에서 부모 객체인지 자식 객체인지 확인하는데 사용한다.
    [사용방법]
    객체 instanceof 클래스
    
    (예)
    animal instanceof Tiger
    >> animal 객체는 Tiger 클래스로 만들어진 객체인가?

동물 클래스가 추가될 때마다 분기문이 추가되는 것은 좋지 않다. 그러므로 위 예제 코드에서 barkable 인터페이스를 생성해보자.

  • 변경 후

    interface Predator{
      (...)
    }
    
    interface Barkable{  //추가
      void bark();
    }  
    class Animal{
      (...)
    }
    
    class Tiger extends Animal implements Predator,Barkable{
      public String getFood(){
        return "appel";
      }
      public void bark(){ // 추가
        System.out.println("어흥");
      } 
    }
    class ZooKeeper{
      (...)
    }
    class Bouncer{
      void barkAnimal(Barkable animal){ //Animal 대신 Barkable 사용
        animal.bark();
      }
    }
    public class Sample{
      (...)
    }  

    인터페이스는 위에서 보듯 콤마(,)를 통해 여러개를 implements 할 수 있다. 따라서 Tiger, Lion 클래스는 Predator 인터페이스와 Barkable 인터페이스를 implements 하였다. 또한 Tiger, Lion 클래스에 bark 메소드를 구현하면 Bouncer 클래스의 barkAnimal 메소드를 위처럼 수정할 수 있다.

    다음은 barkAniml 메소드의 변경 전/후 모습이다.

    • 변경 전
      void barkAnimal(Animal animal){
        if(animal instanceof Tiger){
          System.out.println("어흥")'
        }else if(animal instanceof Lion){
          System.out.println("으르렁");
        }
      }  
    • 변경 후
      void barkAnimal(Barkable animal){
        animal.bark();
      }
      1. barkAnimal 메소드의 입력 자료형이 Animal에서 Barkable로 변경
      2. animal 객체 타입 확인해 "어흥"or"으르렁" 출력 부분은 bark 메소드 호출로 변경

폴리모피즘을 통해 복잡한 형태의 분기문을 간단하게 처리할 수 있는 경우가 많다.

위 예제에서 사용한 tiger,lion 객체는 각각 Tiger/Lion의 클래스의 객체이며 Animal의 객체와 Barkable/Predator 인터페이스의 객체이기도 하다. 이로 인해 barkAnimal 메소드의 입력 자료형을 Animal에서 Barkable로 바꾸어 사용할 수 있는 것이다.

  • 이렇게 하나의 객체가 여러개의 자료형 타입을 갖는 것을 다형성(Polymorphism)이라 한다.

즉, Tiger 클래스의 객체는 다음과 같이 여러 자료형으로 표현할 수 있다.

Tiger tiger = new Tiger(); // Tiger is a Tiger
Animal animal = new Tiger(); // Tiger is a Animal
Predator predator = new Tiger(); // Tiger is a Predator
Barkable barkable = new Tiger(); // Tiger is a Barkable

여기서 알아야 할 점은 선언된 객체별로 사용할 수 있는 메소드가 서로 다르다는 것이다(Predator 객체.메서드!= Barkable 객체.메서드)
만약, Predator의 getFood메서드와 Barkable의 bark 메서드를 동시에 사용하고 싶다면 어떻게 할까?

첫번째, Predator, Barkable 인터페이스를 구현한 Tiger로 선언된 tiger 객체를 사용한다.
두번째, getFood, bark 메소드를 모두 포함하는 새로운 인터페이스를 새로 만들어 사용한다.

interface Predator{
  (...)
}
interface Barkable{
  void bark();
}

//추가
interface BarkablePredator extends Predator, Barkable{
}
(...)

기존 인터페이스를 상속해 BarkablePredator를 만들었다. 이와 같은 방법은 각각 인터페이스의 메소드를 그대로 상속할 수 있으며, 이는 인터페이스가 가진 다중 상속의 특징이다.
(일반 클래스는 단일 상속만 가능)


전체 소스 코드


interface Predator{
    String getFood();

    default void printFood(){
        System.out.printf("My food is %s\n", getFood());
    }
    int LEG_COUNT = 4; //인터페이스 상수

    static int speed(){
        return LEG_COUNT*30;
    }
}

interface Barkable{
    void bark();
}

interface BarkablePredator extends Predator, Barkable{
}
class Animal{
    String name;

    void setName(String name){
        this.name=name;
    }
}

class Tiger extends Animal implements Predator,Barkable{
    public String getFood(){
        return "apple";
    }
    public void bark(){
        System.out.println("어흥");
    }
}
class Lion extends Animal implements Predator,Barkable{
    public String getFood(){
        return "banana";
    }
    public void bark(){
        System.out.println("으르렁");
    }
}
class ZooKeeper{
    void feed(Predator predator){
        System.out.println("feed"+predator.getFood());
    }
}

class Bouncer{
    void barkAnimal(Barkable animal){
        animal.bark();
    }
}

public class test{
    public static void main(String[] args) {
        Tiger tiger = new Tiger();
        Lion lion = new Lion();

        Bouncer boucer = new Bouncer();
        boucer.barkAnimal(tiger);
        boucer.barkAnimal(lion);
    }
}
profile
뚝딱뚝딱

0개의 댓글