인터페이스의 일부만 구현하는 방법


14

OOP에서 개발할 때 때때로 인터페이스 / 계약은 변경할 수없는 라이브러리에 의해 제공됩니다. 이 인터페이스를 J라고합시다.

이제이 인터페이스를 구현하는 객체를 사용하는 클래스 A의 객체가 있습니다. 내부 인터페이스 정의의 작은 부분 만 필요합니다. 일부 객체 클래스는 프로젝트 중에 나에 의해 생성되므로 (D 유형 중 하나라고 부릅니다) 인터페이스 J 내부의 모든 구현에 오버 헤드가 있습니다.

인터페이스 J에서 기능의 하위 집합을 구현하려고하지만 지금까지 내 솔루션이 만족스럽지 않습니다.

  • J의 모든 측면을 구현 한 다음 "notImplementedExceptions"를 발생 시키면 객체의 사용자에게 잘못된 정보를 제공합니다. 유형 D의 객체가 인터페이스 J를 준수하는 것처럼 보이지만 그렇지 않습니다. J) 객체의 무결성에 의존 할 수 없습니다.
  • 인터페이스 J는 내 인터페이스와 완전히 호환되지만 새로 정의 된 인터페이스를 구현하면 인터페이스 J 만 구현하는 객체를 사용할 수 없습니다.
  • 내 사용자 정의 객체가 인터페이스 J를 구현하게하면이 모든 기능이 필요하지 않기 때문에 상당한 오버 헤드가 발생합니다.

인터페이스 J를 변경할 수있을 때 인터페이스 J의 기능 중이 하위 집합을 가진 "슈퍼 인터페이스"K를 만들고 인터페이스 J를 인터페이스 K에서 상속하도록 만들었습니다. 그러나 인터페이스 J를 변경할 수는 없습니다.

이 문제에 대한 객체 지향 솔루션은 무엇입니까? 가장 좋은 솔루션은 여전히 ​​"그냥"인터페이스 J를 구현하고 있습니까? 아니면 인터페이스를 변경하지 않고 인터페이스를 "슈퍼 클래스"하는 OOP 방식이 있습니까?


1
Swing의 * Adapter 클래스가이를 수행하는 방법을 참조하십시오.

답변:


9

인터페이스 J를 제어하지 않으면 문제가 발생한 것입니다.

명확하게, 자신의 인터페이스 subJ 인터페이스 J를 구현 하고 , 자신의 코드에서 subJ를 사용하여 인터페이스 J의 추가 메소드가 필요하지 않다는 것을 분명히 할 수 있지만 실제로 많은 이점을 얻지는 못한다고 생각합니다.

가능하면 전체 인터페이스 J를 완전히 구현하십시오.

가능하면 인터페이스 J의 소유자에게 연락하여 용도에 맞게 변경하도록 요청하십시오.


2
타협 : 인터페이스 J의 소유자에게 더 작은 인터페이스 SubJ로부터 상속을 요청할 수 있습니다.
k3b

27

인터페이스 구현의 요점은 구현 세부 사항이 다를 수 있지만 변경하지 않는 발신자와 수신자 사이의 확고한 계약을 제공하는 것입니다.

인터페이스 J를 구현하면 외부 세계에 할 수있는 일을 알 수 있습니다.

J가하는 것의 절반이 필요하지 않다면 인터페이스는 가능한 한 작지 않은만큼 세분화되거나 NotImplementedException필요하지 않은 메소드와 속성 을 던져야 합니다. 그러나 이것은 코드가 할 수있는 일에 대한 사람들의 기대를 혼란스럽게하므로 최상의 솔루션은 아닙니다.


5

소비자 클래스 A에 모든 인터페이스 J가 필요하지 않은 경우 필요한 모든 것을 포괄적으로 설명하는 새 인터페이스 (K라고 함)를 만드는 것이 좋습니다.

이것은 클래스 A를 사용하는 사람에게 계약 측면이 무엇인지에 대한 명확한 신호를 제공합니다. 이에 의해 재사용 가능성이 향상된다. 누군가가 크고 복잡한 인터페이스를 구현하는 객체를 제공 해야하는 경우 비교적 간단한 작업을 수행하려면 클래스 A 가하는 모든 작업을 작성하게 될 것입니다.

클래스 A가 인터페이스 J 만 구현하는 객체를 소비 할 수 있도록 인터페이스 K를 구현하고 적절한 호출을 인터페이스 J 멤버에 전달하는 래퍼 클래스를 제공 할 수 있습니다.


3

J를 완전히 구현해야하거나 (구현되지 않은 메소드 제외) 전혀 필요하지 않다는 기존 답변에 동의하지만 가능한 해결 방법은 다음과 같습니다.

  • J의 서브 세트 인 더 작은 인터페이스 K를 작성하고 필요한 메소드를 구현하십시오.
  • J와 K를 구현하는 객체를 허용하는 A에 대한 래퍼를 만듭니다.
  • J로 전달 된 경우 간단히 A의 인스턴스로 밀어 넣으십시오.
  • K로 전달 된 경우 J의 익명 구현을 인스턴스화하고 K에서 J까지의 메소드 만 연결하십시오. 결과를 A의 인스턴스로 전달하십시오.

본질적으로 동일한 여러 항목을 허용하는 랩퍼가 필요하기 때문에 이것은 매우 추악한 솔루션입니다. 그러나 다음을 달성합니다.

  • J 또는 A로 변경되지 않습니다.
  • 불완전한 J의 "노출 된"구현은 없습니다.

OO 언어가 익명 인터페이스 인스턴스화를 허용하지 않는 경우, 인터페이스의 더미 구현을 작성하고 인스턴스화 할 수 있습니다.


1

전체 인터페이스를 구현하는 데 얼마나 걸립니까?

상당한 시간이 걸리면 이것은 디자인 문제를 나타내며 (Steven A.가 전에했던 것처럼) 소유자에게 연락하여 나중에 변경 될 수 있는지 확인하도록 조언합니다.

인터페이스 라이브러리와 상관없이 자신의 코드에서 인터페이스를 사용합니까?

Steven A.가 제안했듯이 자신의 인터페이스에서 자신의 코드로보고 싶은대로 사용할 수 있습니다. 이것은 적어도 사내 코드를 깨끗하게 유지합니다. 또한 원하는 인터페이스로이를 소유자에게 보낼 수도 있습니다. 아마도 그는 당신에게 동의하거나, 왜 인터페이스가 분리되어서는 안되는지 설명 할 수있을 것입니다.

구현에 사용되지 않은 인터페이스 멤버가 필요합니까?

'지원되지 않음'으로 인해 호출되지 않을 것으로 예상되는 경우을 사용하는 것이 NotSupportedException좋습니다. 이 인터페이스를 구현하지 않고이 인터페이스를 지원하지 않습니다.


NotSupportedException그것을 사용 하는 것이 좋은 생각은 그 방법을 지원하지 않는다는 것을 분명히합니다.
ChrisF

@ChrisF : NotImplementedException프로덕션 코드 에만 사용 합니다. 그렇지 않으면 "TODO : Implement this"를 작성합니다. 슬프게도 Visual Studio의 작업 목록에 나타나지 않습니다 . 그러나 실제로는 2 일 이상 구현되지 않은 방법을 거의 남기지 않습니다. Resharper는 이러한 예외를 굵게 표시합니다 (적어도 내 설정에서는). :)
Steven Jeuris 2016 년

0

필요한 것을 구현하고 다른 것에 예외 NoImplementedException을 던지십시오.

이것은 사용의 문제입니다. 인터페이스를 사용하지 않거나 코드가 인터페이스를 사용하지 않는다는 것을 알고 있다면 중복 코드에 시간을 투자 할 필요가 없으므로 시간을 투자하지 마십시오.

당면한 과제를 위해 일하고, 다른 사람들이 인터페이스를 사용하려면 따라야 할 길을 잘 지키십시오.

Java의 많은 인터페이스가 완전히 구현되지 않았습니다.

이것은 아파치의 접근 방식입니다 : http://commons.apache.org/lang/api-2.4/org/apache/commons/lang/NotImplementedException.html


아마도 이것이 왜 이것이 올바른 해결책이라고 생각하는지 논쟁하십시오. 이것은 질문에 아무것도 추가하지 않습니다.
Steven Jeuris 2016 년

모든 것을 설명 할 필요가 없으므로 모든 것을 구현할 필요가 없습니다. 그의 경우라면, 인터페이스의 일부가 중복되어 그는 즉시 그것을 선택할 것입니다.
표시 이름
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.