나는 숫자를 가지고있다.Processor
매우 다른 두 가지 일을하지만 공통 코드에서 호출되는 클래스 ( "제어 반전"상황).
나는 당신이 모든 것을 상속해야하는지 결정할 때 어떤 디자인 고려 사항을 내가인지했는지 (또는 당신이 알고있는, 당신이 USS를 위해) 있어야하는지 궁금합니다.BaseProcessor
, 또는 구현IProcessor
인터페이스로.
일반적으로 규칙은 다음과 같이 바뀝니다.
이를 좀 더 구체적으로 설명하기 위해 예제를 살펴 보겠습니다. 그만큼System.Drawing.Bitmap
수업이다이미지 (그리고 그 자체로, 그것은Image
클래스)뿐만 아니라할수있다처리하기 때문에IDisposable
인터페이스. 또한할수있다직렬화, 그래서 그것은에서 구현ISerializable
인터페이스.
그러나 실제로는 C #에서 다중 상속을 시뮬레이션하는 데 종종 인터페이스가 사용됩니다. 귀하의Processor
클래스는 다음과 같은 것을 상속해야합니다.System.ComponentModel.Component
, 당신은 선택의 여지가 있지만IProcessor
인터페이스.
사실 인터페이스와 추상 기본 클래스는 특정 클래스가 수행 할 수있는 작업을 지정하는 계약을 제공합니다. 이 계약을 선언하기 위해 인터페이스가 필요하다는 것은 일반적인 신화이지만 올바른 것은 아닙니다. 내 생각에 가장 큰 이점은 추상 기본 클래스를 사용하면 하위 클래스에 기본 기능을 제공 할 수 있다는 것입니다. 그러나 기본 기능이 없다면 메서드 자체를 다음과 같이 표시하지 않아도됩니다.abstract
파생 된 클래스는 인터페이스를 구현하는 것처럼 스스로 구현해야합니다.
이와 같은 질문에 대한 답변을 보려면 종종.NET Framework 디자인 지침이 클래스와 인터페이스 사이의 선택에 대해 말하고있다 :
일반적으로 클래스는 추상화를 노출하기 위해 선호되는 구조입니다.
인터페이스의 주요 단점은 API의 진화를 허용 할 때 클래스보다 훨씬 융통성이 부족하다는 것입니다. 인터페이스를 출시하면 멤버 세트가 영원히 고정됩니다. 인터페이스를 추가하면 인터페이스를 구현하는 기존 유형이 손상됩니다.
클래스는 훨씬 더 많은 유연성을 제공합니다. 이미 배송 된 수업에 회원을 추가 할 수 있습니다. 메소드가 추상적이 아닌 한 (즉, 메소드의 기본 구현을 제공하는 한) 기존 파생 클래스는 변경되지 않고 계속 작동합니다.
[. . . ]
인터페이스를 선호하는 가장 일반적인 주장 중 하나는 구현과 계약을 분리 할 수 있다는 것입니다. 그러나 인수는 클래스를 사용하여 구현과 계약을 분리 할 수 없다고 잘못 가정합니다. 구체적인 구현과는 별도의 어셈블리에있는 추상 클래스는 이러한 분리를 달성하는 좋은 방법입니다.
일반적인 권장 사항은 다음과 같습니다.
크리스 앤더슨 (Chris Anderson)은이 마지막 교리와 특별한 협약을 맺어 다음과 같이 주장했다.
추상 유형은 훨씬 더 나은 버전을 제공하고 향후 확장 성을 허용하지만, 유일한 기본 유형을 구울 수도 있습니다. 인터페이스는 실제로 시간이 지남에 따라 변하지 않는 두 객체 사이의 계약을 정의 할 때 적합합니다. 추상 기본 유형은 유형 패밀리에 대한 공통 기본을 정의하는 데 적합합니다.
리차드,
왜 그들 사이를 선택 하는가? IProcessor 인터페이스가출판 된유형 (시스템의 다른 곳에서 사용하기 위해); IProcessor의 다양한 CURRENT 구현에 공통적 인 동작이있는 경우에는 추상 BaseProcessor 클래스가 해당 공통적 인 동작을 구현하는 실제 좋은 장소가됩니다.
이런 방식으로, 미래에 BaseProcessor의 서비스를위한 것이 아닌 IProcessor가 필요하다면, 그것을 가지고 있지 않을 수도 있고 가능하게 숨길 수도 있습니다 ...하지만 그것을 원한다면 ... 줄일 수 있습니다. 중복 코드 / 개념.
내 겸손한 견해.
건배. 키이스.
인터페이스는 "계약"이며, 이는 몇 가지 클래스가 원하는 멤버 집합 (속성, 메서드 및 이벤트)을 구현하도록합니다.
기본 클래스 (구체적 또는 추상, 중요하지 않음)는 일부 엔티티의 원형입니다. 이것이 실제 물리적 또는 개념적 공통점을 나타내는 개체입니다.
인터페이스를 언제 사용합니까?
어떤 유형은 선언 할 필요가있을 때마다 적어도 소비자가 관심을 가져야 할 행동과 속성을 가지고 있으며 어떤 작업을 수행하는 데 사용합니다.
기본 클래스 (구체적 및 / 또는 추상)를 사용하는 경우
한 그룹의 엔티티가 같은 아키 타입을 공유 할 때마다 B는 A가 상속 받음을 의미하지만 B는 A가 다르기 때문에 A를 상속 받지만 B는 A로 식별 될 수 있습니다.
예 :
테이블에 대해 이야기 해 봅시다.
우리는 재활용 가능한 테이블을 허용합니다.=>이것은 "IRecyclableTable"과 같은 인터페이스로 정의되어야합니다. 모든 재활용 가능 테이블은 "Recycle"메소드를 갖습니다..
우리는 데스크탑 테이블을 원한다.=>이것은 상속으로 정의해야합니다. "데스크탑 테이블"은 "테이블"입니다. 모든 테이블은 공통적 인 속성 및 동작을 가지며 데스크탑은 데스크탑 테이블이 다른 유형의 테이블과 다르게 작동하도록 동일한 속성 및 동작을 추가합니다.
나는 연관성에 대해 이야기 할 수 있습니다. 객체 그래프에서 두 경우의 의미를 이야기 할 수는 있지만, 제 생각에 개념적 관점에서 논증 할 필요가 있다면, 저는이 논증으로 정확히 대답 할 것입니다.
IRecyclable
인터페이스는 여러 개의무관계의객체는 재활용 할 수 있어야합니다 (즉, 테이블을 나타내지 않는 다른 클래스). 그리고 나서 나는 여전히 모든 테이블을Table
수업 포함DesktopTable
과PicnicTable
과FoldingTable
. - Cody Gray♦
필자는 디자인 선택에별로 좋지 않지만, 확장 된 멤버 만 있다면 iProcessor 인터페이스를 구현하는 것을 선호 할 것입니다. 확장 할 필요가없는 다른 함수가 있으면 기본 프로세서에서 상속하는 것이 더 좋습니다.
디자인의 순결을 제쳐두고, 한 번만 상속 할 수 있습니다. 일부 프레임 워크 클래스를 상속해야하는 경우 질문은 논리적이지 않습니다.
선택의 여지가 있다면 실용적인 방법으로 가장 많은 타이핑을 저장하는 옵션을 선택할 수 있습니다. 어쨌든 평범한 선택입니다.
편집하다:
기본 클래스에 구현이있는 경우 유용 할 수 있습니다. 순수하게 abstact이면 인터페이스 일 수도 있습니다.
선택한 항목이 상관 없으면 항상 인터페이스를 선택하십시오. 더 많은 유연성을 허용합니다. 나중에 변경되지 않도록 보호 할 수 있습니다 (기본 클래스에서 변경해야 할 경우 상속 된 클래스가 영향을받을 수 있음). 또한 세부 정보를보다 잘 캡슐화 할 수 있습니다. Dependency Injection Control의 Inversion of Control을 사용하고 있다면 인터페이스를 선호하는 경향이 있습니다.
또는 상속을 피할 수없는 경우 두 가지를 함께 사용하는 것이 좋습니다. 인터페이스를 구현하는 추상 기본 클래스를 만듭니다. 귀하의 경우, ProcessorBase는 IProcessor를 구현합니다.
ASP.NET MVC의 ControllerBase 및 IController와 유사합니다.
SOLID 원칙은 프로젝트의 유지 보수성과 확장 성을 제공하므로 상속을 통한 인터페이스를 선호합니다.
또한 인터페이스에 "추가 기능"을 추가해야하는 경우 가장 좋은 옵션은 인터페이스 분할 기준 인 SOLID에 따라 새 인터페이스를 모두 만드는 것입니다.