
1. Abstract Method와 Interface의 구분
-
Abstract Method (추상 메소드)
- 추상 클래스 내부에 선언되며, 하위 클래스에서 반드시 구현해야 한다.
- 모든 하위 클래스가 공통적으로 가져야 하지만, 구현 내용은 다를 때 사용한다.
- 예시:
display()
- 모든 오리는 자신을 화면에 표시할 수 있어야 한다.
- 하지만 MallardDuck, RedheadDuck 등 각 오리의 모습이 다르기 때문에 하위 클래스에서 반드시 오버라이드해야 한다.
- 따라서
Duck 클래스에서는 abstract void display();로 선언한다.
-
Interface (인터페이스)
- 특정 동작(행위)의 규격만 정의하며, 다양한 클래스에서 구현할 수 있다.
- 주로 “can-do” 관계일 때 사용한다.
- 예시:
FlyBehavior, QuackBehavior
FlyBehavior는 “날 수 있다/없다”라는 능력의 규격만 정의한다.
QuackBehavior는 “소리를 낼 수 있다/없다”라는 규격만 정의한다.
- 오리뿐만 아니라 다른 객체(예: 로켓, 슈퍼맨)에도 재사용할 수 있다.
2. Abstract Class VS Interface
-
Abstract Class
- 공통 속성과 동작을 공유하면서 일부 동작은 강제로 구현해야 할 때.
- “is-a” 관계일 때 (예: MallardDuck is a Duck).
- 예시:
Duck 클래스의 swim()
- 모든 오리는 물 위에 뜨고 수영한다는 공통 특성을 가진다.
- 따라서
swim()은 상위 클래스인 Duck에 구현 메소드로 둔다.
- 굳이 하위 클래스마다 다시 정의할 필요가 없기 때문에 효율적이다.
-
Interface
- 동작 규격만 정의하고, 구현은 자유롭게 다양할 때.
- “can-do” 관계일 때 (예: Duck can Fly).
- 여러 클래스 계층에서 공유 가능한 동작일 때.
- 예시:
FlyBehavior와 QuackBehavior
- 오리는 날 수도 있고 못 날 수도 있다.
- 오리는 울 수도 있고 못 울 수도 있다.
- 이런 경우 각각을 인터페이스로 분리하면 다양한 전략을 자유롭게 조합할 수 있다.
3. Strategy Pattern과의 연결
-
Abstract Class
Duck 클래스는 모든 오리의 공통 특성을 가진 기본 청사진.
display()는 추상 메소드로 두어 하위 클래스에서 반드시 구현하게 한다.
swim()은 변하지 않는 동작이므로 상위 클래스에서 구현한다.
-
Interface
FlyBehavior, QuackBehavior는 오리의 변하는 동작을 캡슐화.
- 각 인터페이스를 구현한 클래스(
FlyWithWings, FlyNoWay, Quack, MuteQuack, Squeak)는 구체적인 전략을 제공한다.
-
Composition
Duck 클래스는 FlyBehavior와 QuackBehavior를 HAS-A 관계로 가진다.
- 실행 시점(runtime)에 원하는 행동을 주입하거나 교체할 수 있다.
4. 핵심 정리
-
Abstract Method
- “모든 하위 클래스가 가져야 하지만, 구현 내용은 다를 때” 사용.
- 예:
display()
-
Interface
- “다양한 클래스에서 공유 가능한 동작을 규격화할 때” 사용.
- 예:
FlyBehavior, QuackBehavior
-
구현 메소드
- “모든 하위 클래스가 동일하게 사용할 수 있는 공통 동작”일 때 사용.
- 예:
swim()
-
결론:
- 변하지 않는 것은 상위 클래스에서 구현.
- 반드시 있어야 하지만 달라지는 것은 추상 메소드.
- 독립적으로 캡슐화해야 하는 변하는 동작은 인터페이스로 분리.