2012-03-07 2 views
12

일반적으로 인터페이스 또는 추상 클래스가 적절한 결정 인 경우가 있습니까?메소드 선언의 리턴 유형을 인터페이스 클래스 또는 구체적 클래스로해야합니까?

그러나 어떤 경우에는 구체적인 클래스가 더 나은 것처럼 보입니다. 예를 들어,

public string Replace(string old, string new) 

StringReplace 방법은 구체적인 클래스를 반환합니다. 나는 구체적인 클래스를 반환해야 할 때 내가 인터페이스를 반환해야 할 때 내 질문이

  1. 입니다

    (그것은 문자열이 어떤 인터페이스를 구현하지 않더라도 단지 예.,의), 그리고?

  2. 인터페이스를 반환하기 위해 program to an interface, not an implementation의 일부입니까?

답변

4

다릅니다.

나는이 질문을 두 번이나 보았으며 여기에는 "의존적 인"답을 설명하는 좋은 예가 나와 있습니다.

은 다음 클래스를 고려

public class MyClass 
{ 
    public static IEnumerable<int> Test() 
    { 
     return new List<int> { 2, 3, 4 }; 
    } 

    public static List<int> Test2() 
    { 
     return new List<int> { 2, 3, 4 }; 
    } 
} 

TestIEnumerable를 반환하고 Test2IEnumerable 인터페이스 (이 경우에 List)의 구체적인 구현을 반환합니다. 가장 좋은 방법은 무엇입니까? Test 또는 Test2?

사실, 둘 다 의미 다른 : Test으로

  • 는 단지 IEnumerable 반환, 그것은 그것이 개발자가 열거에 반환 된 객체를 사용하는 방법 계약 의 일부 있다는 의미한다 (foreach).
  • List 인스턴스를 반환하므로 인덱스를 사용하여 List의 개체에 액세스 할 수 있습니다. 그것은 반환 된 객체의 완전히 다른 활용입니다.
  • private static void Main(string[] args) 
    { 
        foreach (var z in MyClass.Test()) 
        { 
         Console.WriteLine(z); 
        } 
    
        var f = MyClass.Test2()[0]; 
    
        Console.ReadKey(); 
    } 
    

    당신이 개발자는, 당신은 반환 형식으로 인터페이스를 사용할 수있는 열거에 반환 된 객체를 사용할 것으로 예상되는 경우


. 개발자가 인터페이스의 구체적인 구현 (위의 예제에서 인덱스로 객체에 액세스)의 메서드/속성을 사용하기를 기대하는 경우 구체적인 유형을 반환 할 수 있습니다.

가끔 선택의 여지가 없음을 기억하십시오. 예를 들어 Silverlight 바인딩에 사용해야하는 공용 컬렉션을 노출하려면 바인딩 시스템에 ObservableCollection 클래스의 메서드/속성/동작이 실제로 필요하므로 IEnumerable<T>이 아니라 ObservableCollection<T>을 반환해야합니다 (IEnumerable은 그렇지 않습니다. 바인딩이 작동하기에 충분한).

피해야 할 사항은 IEnumerable<T>을 반환하며 매번 ToList()과 함께 사용되는 메서드입니다.

+0

IEnumerable 을 반환하는 메서드가 싫다면 List 입니다. 일반 for 루프 (인덱스와 함께 참조 항목)를 사용할 수 없거나 LINQ Count 메서드를 사용하지 않고 가장 간단한 Count 메서드를 호출 할 수도 없습니다. 내가하는 모든 것이 목록을 반환 할 때 사용하는 반환 형식은 IList 입니다. yield return과 함께 사용하면 IEnumerable 만 반환합니다. 한 편 : 공용 라이브러리를 개발할 때 IEnumerable을 사용하면 더 많은 이점을 얻을 수 있습니다. – Nullius

1

나는 Program to an interface, not an implementation을 잘못 생각하고 있습니다. GOF가 프로그램에서 인터페이스를 의미하는 것은 유형의 인터페이스입니다.

외부에서 볼 수있는 모든 방법으로 개체 인터페이스를 정의합니다. 따라서이 경우의 인터페이스 정의는 예를 들어 C#에서 사용하는 것과 다릅니다.

귀하의 질문에 대해서는 아마도 추상적 인 클래스를 반환하는 것이 더 좋을 것이라고 생각합니다. 추상 클래스에서 파생 된 객체를 반환하면 작동합니까? 그렇다면 추상 클래스를 반환합니다. 그렇지 않으면보다 구체적으로 이동하고 파생 형식을 반환하십시오.

+0

'유언을 통치하는 프로그램'에 대한 자세한 내용은 Erich Gamme와의 인터뷰 (http://www.artima.com/lejava/articles/designprinciples)를 참조하십시오.html – sloth

+0

@squelos'인터페이스 프로그래밍 '은 단지 메소드 인터페이스를 반환한다는 의미는 아닙니다. 내 API가 인터페이스를 반환하면 API를 사용하는 사용자가 '프로그래밍 인터페이스'를 수행 할 수 있습니다. 구체적인 클래스를 반환하면 사용자가 인터페이스를 강제로 사용할 수 없습니다. –

+0

오, 나는 그것을 잘못 알고 있었다. 나는 당신이 "인터페이스"로 이해하고 있었던 것에 대해 의심스러워서 분명히하기를 좋아했습니다. 문제가 없습니다 – squelos

3

제 생각에는 밀접하게 결합 된 방식으로 사용되는 메소드가 있다면 클래스 2의 메소드 A는 클래스 A를 호출하고 항상 특정 유형을 원하며 그 메소드가 호출 된 유일한 시간입니다 아무런 의미가 없다고 주장 할 수 있습니다. 예를 들어 IEnumerable을 반환 할 수 있습니다.이 메서드는 컬렉션을 목록으로 만든 다음 IEnumerable, 클래스 1로 반환 한 다음이를 목록으로 사용하므로 반환 값에 ToList()가 호출되어야합니다.

그러나 데이터 레이어와 같은 클래스 간의 인터페이스를 더 분리 할 때 항상 가장 일반적인 공통 이름 (예 : IEnumarable)을 반환하고 소비자에게 내가 무엇을 결정할 지 결정하지 못하게 할 수 있습니다. 그것으로해라.

0

얼마에 따라 달라집니다 액세스 코드의 사용자에게 제공하고 싶습니다!

사용자에게 List<AccountStatement>을 반환하는 것은 의미가 없습니다. 당신이

그래서 (A 문은 특정 트랜잭션을 예약에 생성을하셔야합니다)이 컬렉션에 새로운 문을 추가하는 코드의 사용자를 좋아하지 않을 것 때문에,이 경우 당신은 IEnumerable<AccountStatement>를 반환 할 수 있습니다 - 읽기 전용 액세스.

  • 액세스를 더 잘 제어 할 수 당신은 외부 세계에 개체에 제공 : 일반적으로

    , 나는 다음과 같은 이유로 방법에서 인터페이스 반환의 생각을지지 않습니다.

  • 당신은 단지 당신이 반환하여 원하는 동작을 노출 (이 글은 줄 인터페이스 독방의 원리입니다
  • (즉, 예를 들어, 심지어 클래스 어셈블리 내부에 남아있을 수 있습니다) 숨기기 구현 세부에 도착하고 구현 , 오른쪽 인터페이스).

Btw, "string"을 반환하는 예는별로 유용하지 않습니다. 원시 데이터 형식 (mscorlib의 원시 데이터 형식을 의미 함)이며이 개체에서 숨기거나 표시 할 항목이 많지 않습니다.

+0

erm ... 문자열은 기본 유형이 아닙니다. – Sinaesthetic

+0

수정 진술 추가. 나는 이것이 흔히 사용되는 네이티브 데이터 유형이라는 것을 의미했다. –

관련 문제