2010-06-18 11 views
7

C#에서는 클래스 상단에 두 개의 추상 기본 클래스가 있고 클래스의 파생 클래스가 꽤 있습니다. 이러한 몇 가지 구체적인 클래스에는 동일한 속성과 메서드가 동일하게 구현되어 있습니다. 그것은 나를 낭비로 치고 다른 일반적인 기본 클래스에서이 공통적 인 동작을 구현하는 것이 해결책 일 수 있습니다.추상 기본 클래스 대신 일반적인 동작을 구현합니까?

그러나 계층 구조의 다른 여러 클래스가 다른 동작을 공유하고 다른 기본 클래스의 컨트롤 중 하나와 공통점을 공유한다면 어떻게 될까요? 아마도 공통성의 영역이 많이있을 것입니다. 추상 기본 클래스 구현으로 이것을 모델링하는 것은 비현실적일까요?

abstract class FlashableControl: Control 
{ 
    public int FlashyProperty; 
    public void FlashMethod(); 
}; 

class StatusBar: FlashableControl; // but it's also a bit square too, hmm... 

그렇다면 기본 클래스를 사용하지 않고 이러한 구현을 클래스간에 어떻게 공유 할 것입니까?

인터페이스의 구현을 다른 클래스에 위임하고 해당 클래스가 원하는 클래스를 대신하여 해당 속성과 메서드를 구현하도록하여 사용자에게 표준 인터페이스를 지원하도록 StatusBar와 Window가 표시되도록하려는 것이 상상입니다. , 그러나 그것을 커버하는 것은 그것을 구현하는 다른 것입니다.

이 동작을 구현하는 집계 클래스를 시각화 할 수 있지만 이것이 적절하며 함정이 있습니까? 대안은 무엇입니까?

감사

+0

FlashMethod, SquarishProperty 등은 기본 클래스에 구체적으로 구현되어 있습니까? 아니면 추상 클래스입니까? – SWeko

+0

여기서는 추상 구현 방법을 설명하기 위해 실제 구현에서 많은 구현 클래스가 있지만 실제 인터페이스 (인터페이스 및 메서드)는 동일하지만 인터페이스는 동일합니다. – DaBozUK

답변

3

는이 같은 패턴을 사용할 수 있습니다 ICommonServices을 구현

public interface ICommonServices 
{ 
    string SomeProperty { get; set; } 

    void SomeMethod(string param); 
} 

public static class CommonServiceMethods 
{ 
    public static void DoSomething(this ICommonServices services, string param) 
    { 
     services.SomeMethod(services.SomeProperty + ": " + param + " something extra!"); 
    } 
} 

모든 수업을 이제 모든 ICommonServices의 구현에 의해 노출 된 이러한 기능에 전적으로 의존하는 확장 메서드를 통해 일부 무료로 동작을 얻을. 기본 클래스 기능에 액세스해야하는 경우 자체 인터페이스에 ICommonServices가 해당 인터페이스를 구현하도록 할 수 있습니다. 이제 여러 기본 클래스를 사용할 필요없이 인터페이스에 대한 '기본'확장 기능을 만들 수 있습니다.


편집

이러한 방법 중 일부는 내부 싶은 경우,이 같은 패턴을 수정할 수 있습니다

public class MyObject : IServices 
{ 
    public string PublicProperty { get; private set; } 

    string IServices.SomeProperty { get; set; } 

    void IServices.SomeMethod(string param) 
    { 
     //Do something... 
    } 
} 

public interface IPublicServices 
{ 
    string PublicProperty { get; } 
} 

internal interface IServices : IPublicServices 
{ 
    string SomeProperty { get; set; } 

    void SomeMethod(string param); 
} 

internal static class ServiceMethods 
{ 
    public static void DoSomething(this IServices services, string param) 
    { 
     services.SomeMethod(services.SomeProperty + ": " + param + " something extra!"); 
    } 
} 

기본적으로 우리가 노출하고 공공 및 내부 인터페이스 모두를. 공용 클라이언트가 인터페이스 유형에 액세스 할 수 없으므로 메서드를 공용으로 사용할 수 없도록 내부 인터페이스 메서드를 명시 적으로 구현합니다.이 경우 헬퍼 확장 메서드는 내부적이며 공용 인터페이스에 의존하는 공용 도우미 메서드를 만들 수도 있습니다.

+0

Microsoft Unity IoC 컨테이너도이 트릭을 사용합니다. –

+0

이 접근법은 정말 좋으며 구현에 옮길 것입니다. 이 클래스를 다른 어셈블리의 클라이언트 코드에서 숨기는 가장 좋은 방법은 무엇입니까? Boz – DaBozUK

+0

@DaBozUK, 내부 액세스 만 제공하는 방법에 대한 예를 들어 답변을 수정했습니다. –

3

당신이 사용할 수있는 '이-A' '- A는'와

class Window : Control, ISquareControl 
    { 
     private SquareControl square; 

     public void SquareOperation() 
     { 
      square.SquareOperation(); 
     } 
    } 

    class SquareControl : Control, ISquareControl 
    { 
     public void SquareOperation() 
     { 
      // ... 
     } 
    } 
+0

이것은 집계 접근법에 대해 염두에 두었던 것이므로 SquareControl 클래스를 내부에 유지하여 Window 사용자로부터 숨길 수 있기를 바랍니다. 이 접근 방식, 제한 사항 또는 문제가있는 함정이 있습니까? – DaBozUK

0

한 가지 방법은 인터페이스 및 기본 클래스를 사용하는 것입니다 내부 광장 제어 위임 대신.

Flashable은 클래스 대신 좋은 인터페이스를 만듭니다.

+0

인터페이스와 기본 클래스는 내가 위에서 피하면서 싶었던 것입니다. 문제는 클래스의 여러 가지 집합이 일부 동작을 공유하지만 모든 동작을 공유하지 않으면 클래스 계층 구조가 복잡해질 수 있다는 것입니다. – DaBozUK

관련 문제