본문 바로가기
프로그래밍 놀이터/디자인 패턴, 리펙토링

[Design Pattern/Java] 추상 클래스보다는 인터페이스를 사용하자.

by 돼지왕 왕돼지 2012. 3. 29.
반응형



안녕하세요 돼지왕 왕돼지입니다.

오늘은 "추상 클래스보다는 인터페이스를 사용하자" 라는 주제로 이야기를 해볼가 합니다.

이 글은 "Effective Java" 의 내용을 요약 정리한 것입니다.


추상 클래스와 인터페이스의 General 한 차이점

- 추상 클래스는 구현된 메소드( 메소드 몸체 코드가 있는.. ) 를 포함할 수 있는 반면, 인터페이스는 그렇지 못합니다.

- 추상 클래스로 정의된 타입을 구현하는 클래스는 반드시 추상 클래스의 서브 클래스가 되어야 합니다. 반면 인터페이스를 구현하는 클래스의 경우는, 인터페이스에 정의된 모든 메소드를 구현하고 인터페이스 구현 계약을 지키면 됩니다. 즉 클래스 상속 계층과는 무관합니다.

- 클래스 간의 상속은 단일상속만을 허용하므로, 추상 클래스로 타입을 정의할 때는 심한 제약이 따릅니다. 반면 인터페이스를 구현하는 것은 매우 쉽습니다.


 


어떤 점에서 interface 가 abstract class 에 비해 좋은가?

- 만일 한 클래스가 두개의 추상 클래스를 상속받고자 한다면, 추상 클래스 중 하나를 한 단계 위로 올려서 추상 클래스 하나가 최상위의 조상 클래스가 되도록 해야 합니다. 그리고 이것은 타입계층에 큰 손상이 됩니다. 좋든 싫든 모든 후손 클래스들이 이 최상위 추상클래스를 상속받아야 하기 때문입니다. 

- 반면 인터페이스는 믹스인(mixin) 을 정의하는데 이상적입니다. 믹스인은 본래 타입에 추가하여 구현할 수 있는 타입으로, 섞는 것( mix in )이 가능한 것을 말합니다. 그래서 인터페이스는 비계층적인 타입 프레임워크를 구축할 수 있게 해줍니다. 위와 같이 계층화가 일어나지 말아야 하는 경우에 특히 인터페이스를 사용하는 것이 더 효율적입니다.

- 이전에 나온 글에서도 나오다시피, 상속에는 치명적인 약점들이 있기 때문에 피해야 좋습니다.
2012/03/29 - [프로그래밍 놀이터/디자인 패턴] - [Design Pattern/Java] 가급적 상속(Inheritance) 보다는 컴포지션(composition)을 사용하자.  




하지만, interface 는 몸통을 포함하지 않는다는 약점이 있지 않습니까?

- 네 그렇습니다. 이 약점은 cover 하기가 힘듭니다. 하지만, 어느 정도 완화할 수 있는데 이럴 때 사용되는 것이 골격 구현 ( skeletal implementation ) 추상 클래스입니다. 작명 규칙은 Abstract[Interface이름] 으로 합니다. 골격 구현 클래스의 설계를 잘 하면, 그 클래스와 연관된 인터페이스를 프로그래머가 매우 쉽게 구현할 수 있습니다.
( 예제를 봐야 이해를 도울 수 있는데, 이는 책을 직접 참고하세요 :P )

- 골격 구현 클래스를 사용하면, 추상 클래스로 타입을 정의할 때 생기는 과도한 제약에 해당되지 않고, 추상 클래스로 구현하는데 도움을 줄 수 있습니다. 대부분의 인터페이스 구현은 골격 구현 클래스로부터 상속받아 하는 것이 당연하겠지만, 어디까지나 그것은 선택 사항입니다. 만일 기존 클래스가 골격 구현 클래스로부터 상속 받을 수 없다면, 그 클래스는 인터페이스를 직접 구현할 수 있으며, 골격 구현 클래스는 여전히 구현 측의 작업에 도움을 줄 수 있습니다. 인터페이스를 구현하는 클래스에서는 자신이 포함하는 private 내부 클래스 인스턴스로 인터페이스 메소드 호출을 전달할 수 있으며, 내부 클래스는 골격 구현 클래스로부터 상속 받는 서브 클래스로 정의하면 됩니다. 이런 기법을 모의 다중 상속 ( simulated multiple inheritance ) 라고 합니다.

[골격 클래스 구현은 어떻게 하나요?]

 
- 골격 클래스는 사실 상속을 위해 정의된 클래스이기 때문에 그에 따른 설계와 문서화 작업을 꼭 해주어야 합니다.
2012/03/29 - [프로그래밍 놀이터/디자인 패턴] - [Design Pattern/Java] 상속을 위한 설계와 문서화를 하자. 그렇지 않다면 상속의 사용을 금지시킨다. 




추상화 클래스의 장점은 없는가?

- 인터페이스보다는 추상화 클래스를 진화시키는 게 훨씬 더 쉽습니다. 만일 향후 배포판에서 새로운 메소드를 추상 클래스에 추가하고 싶다면, 기본적인 구현 코드를 포함하는 실체 메소드를 추가할 수 있습니다. 그럼 추상 클래스를 상속받는 모든 기존 클래스에서도 그 새 메소드를 사용할 수 있는 것이지요. 하지만 인터페이스는 그렇지 않습니다. 만일 인터페이스에 메소드를 추가한다면, 그 인터페이스를 구현했던 클래스들은 새로운 메소드의 구현이 빠져있어 컴파일이 되지 않습니다. 물론 인터페이스와 골격 구현 클래스 모두에 새로운 메소드를 추가하는 방법이 필요하지만, 이녀석도 손이 가죠.

- 따라서 인터페이스는 신중하게 설계해야 합니다. 일단 인터페이스가 배포되어 널리 사용되면 변경이 거의 불가능합니다. 그래서 처음부터 올바르게 만들어야 합니다. 배포하기 전에 반드시 해야 할 일은, 많은 프로그래머들이 그 인터페이스를 구현하도록 하는 것입니다. 그래서 가능한 기간 내에 많은 결함을 발견해내어 인터페이스를 올바르게 수정해야 합니다. 



 
도움이 되셨다면 손가락 꾸욱~



 
반응형

댓글