다형성 예제로 이해하기

객체 지향 프로그래밍의 꽃이라고 할 수 있는 다형성을 예제를 통해 쉽게 알아보겠습니다. 코드의 중복을 줄이고, 변경에 유연한 코드를 작성하기 위해서는 다형성을 이해할 필요가 있습니다. 다른 사람이 작성한 코드를 이해하거나 스프링과 같은 프레임워크를 이해하기 위해서도 반드시 알고 있어야 하는 필수적인 개념입니다. 다형성을 이해하려면 먼저 프로그래밍에서 말하는 추상화에 대한 이해가 필요합니다.

추상화란?

다형성추상화와 깊은 연관이 있습니다. 코드를 작성할 때 구현체에 의존하는 코드를 작성하는 것이 아니라 추상화된 클래스에 의존하는 코드를 작성하면 다형성의 이점을 누릴 수 있게 됩니다.

추상화란 한마디로 공통적인 특성을 뽑아내는 것을 말하는데, 대표적으로 자바 언어의 interface를 추상화의 예로 들 수 있습니다. interface는 자신을 구현하는 클래스가 어떤 메서드를 제공해야 하는지를 정의합니다. 그리고 자신을 구현한 클래스는 반드시 그 메서드를 제공하도록 강제합니다. 즉, 어떤 클래스가 interface를 구현(implements)하는 것은 해당 클래스에 특정 역할을 부여하는 것과 같습니다. 예를 들어, 어떤 클래스가 사람을 추상화한 Person이라는 인터페이스를 구현하면 해당 클래스는 Person의 역할을 수행하게 되는 것입니다. 우리는 Person interface를 구현한 클래스를 Person 구현체라고 부릅니다.

다형성 예제로 이해하기

Person의 구현체로 Greenneuron이라는 클래스를 만들어 보겠습니다.

/**
 * 사람을 추상화한 인터페이스
 */
interface Person { 
  void eat();
  void sleep();
}

물론 사람이 먹고 자기만 하는 것은 아니지만, 사람이 할 수 있는 수많은 행동들 중에 개발자가 임의로 두 가지의 행동을 꼽은 겁니다. “사람이라면 먹고 자는 일을 할 수 있어야 해!” 라고 정의하는 것이죠. 사실 개발자가 만들고 있는 가상 세계에서 사람이 날 줄 알아야 한다면 fly 메서드를 추가할 수도 있습니다.

class Greenneuron implements Person {

  /**
   * 먹는 일을 수행합니다.
   */
  @Override
  public void eat() {
    System.out.println("빵을 먹는다.");
  }

  /**
   * 자는 일을 수행합니다.
   */
  @Override
  public void sleep() {
    System.out.println("4시간 잔다.");
  }

}

위 코드는 Greenneuron이라는 클래스가 Person을 구현한 것을 보여줍니다. Grenneuron은 먹고 자는 일을 할 수 있어야 합니다.(해당 메서드들을 반드시 구현해야 함) 그리고 우리가 객체에게 일을 시킬 때는 행동에 자율성을 부여합니다. 자율성을 부여한다는 것은 메서드를 호출했을 때 동작하는 내부 로직은 개발자가 구현하기 나름이라는 것을 의미합니다. 제가 구현한 Greenneuron 클래스는 빵만 먹을 수 있고, 잠은 4시간만 잘 수 있습니다. 당연한 말이지만 eat 메서드를 호출했는데 토를 한다거나 이상한 행동을 하게 만들면 안 됩니다. 그래야 객체지향과 다형성의 이점을 얻을 수 있습니다.

Person person = new Greenneuron(); //Greenneuron 클래스는 Person의 구현체
person.eat();
person.sleep();

위 코드는 person이 먹고 자는 것을 순서대로 수행하는 코드입니다. 따라서 eat 메서드는 반드시 먹는 일을 수행해야 하고, sleep 메서드는 반드시 자는 일을 수행해야 합니다. 눈여겨 보아야 할 것은 참조 변수인 person의 자료형이 Person인데 Greenneuron 이라는 클래스의 인스턴스를 할당하고 있다는 점입니다. 다형성이라는 특성 덕분에 이런 코드를 작성할 수 있습니다.

클래스 다이어그램으로 표현하기

Greenneuron 클래스는 Person 클래스를 구현한다

Greenneuron 클래스가 Person 클래스를 구현할 때 두 클래스의 관계는 위와 같이 표현합니다. (구현 관계)

※ 상속 관계의 경우 점선이 아니라 실선으로 표현합니다. 그런데 편의에 따라 점선과 실선을 구분하지 않고 모두 실선으로 표현하는 경우도 있습니다.

다형성의 장점

이제 우리는 코드를 작성할 때 Person의 역할에만 집중하여 코드를 작성할 수 있게 되었습니다. 참조 변수인 person을 사용해 코드를 작성해두면, 만약 Greenneuron 클래스의 인스턴스가 아니라 다른 Person 구현체를 person 변수에 할당하더라도 객체를 할당하는 코드 외에는 수정할 필요가 없습니다. person 변수에 할당된 객체는 자율적으로 먹고 자는 일을 수행하게 되며 여전히 정상적으로 동작할 것입니다. 이것이 바로 다형성의 장점입니다. 다형성을 잘 활용하면 코드의 중복을 줄이고 변경에 유연한 코드를 작성할 수 있게 됩니다.

※ 다형성은 상속에서의 부모 클래스와 자식 클래스 사이에서도 적용됩니다. 참조 변수의 자료형이 Parent클래스라면 Parent를 상속받는 클래스의 인스턴스를 할당할 수 있습니다.

스스로 경험하며 얻은 깨달음을 공유하기 좋아하며, 세상이 필요로 하는 코드를 작성하기 위해 노력하는 개발자입니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다