2013-05-13 2 views
3

:제네릭 및 다음 클래스 및 인터페이스를 감안할 때 인터페이스 문제

public class Test<T> 
{ 
} 

public interface ITesting<T> 
{ 
    Test<T> LoadTest(); 
} 

나는 다음과 같이 클래스를 추가 할 수 있습니다

잘 작동과 오류가 발생하지 않습니다
public class TestManager : ITesting<object> 
{ 
    #region ITesting 

    public Test<object> LoadTest() 
    { 
     return new Test<object>(); 
    } 

    #endregion 
} 

. 나는 다음과 같이 클래스를 대체하려고하면 :

public class TestDerived : Test<object> 
{ 
} 

public class TestDerivedManager : ITesting<object> 
{ 
    #region ITesting 

    public TestDerived LoadTest() 
    { 
     return new TestDerived(); 
    } 

    #endregion 
} 

지금 다음 오류 얻을 :

 
Error 'TestDerivedManager' does not implement interface member 'ITesting.LoadTest()'. 'TestDerivedManager.LoadTest()' cannot implement 'ITesting.LoadTest()' because it does not have the matching return type of 'Test'. 

를하지만 나에게 TestDerivedTest<object> 같이 작동합니다 같이 보인다. 나는 분명히 여기 뭔가 정확하게 이해하지 못하고있다. 누군가가 왜 이것이 잘못된 이유에 대한 세부 사항을 지적 할 수 있습니까? 그리고 아마도 그것을 교정하기 위해 무엇을 할 수 있을까요?

+3

이 동작에는 제네릭과 관련이 전혀 없습니다. 만약 당신이'interface I {Animal M(); } 클래스 C : I {공개 기린 M() {새 기린 반환(); }}'같은 에러가 나옵니다. –

답변

6

는 반환 형식 공분산이라고 할 기능을 :

다음과 같이 변경, 코드 작업을합니다. 그것은 C++의 기능이지만 C#이 아니기 때문에 오류가 무엇을 말하는지해야합니다.

공개 메소드를 호출하는 명시 적 인터페이스 구현을 권장합니다. 그런 식으로 두 세계의 장점을 누릴 수 있습니다.

4

메서드의 반환 형식을 Test<object>으로 변경하면 제대로 작동합니다. 반환 유형은 인터페이스를 구현할 때 계약의 일부입니다. Test<object>이기 때문에 여전히 TestDerived을 반환 할 수 있습니다. TestDerived

+2

그것은 TestDerived가 실제로 테스트 할 때 작동하지 않는 이유를 설명한다고 생각하지 않습니다. cgatian

6

은 예, Test<object>이지만, Test<object>하지TestDerived이다.

ITesting<object>에는 Test<object>을 반환 할 수있는 메서드가 있습니다. 단 하나의 특별한 경우 (TestDerived).

public class TestDerivedManager : ITesting<object> 
{ 
    public Test<object> LoadTest() 
    { 
     return new TestDerived(); 
    } 
} 
3

당신이 찾고있는 것은 "return type covariance"이며 불행히도 C#에서는 지원되지 않습니다. 반환 형식이 원래 반환 형식에서 파생 된 경우에도 원래 서명과 다른 반환 형식을 사용하여 메서드를 재정의 (또는 구현) 할 수 없습니다.

당신은 (수도 있고 좋은 생각되지 않을 수도가있는) 명시 적 인터페이스를 구현하고 당신이 찾고있는 좁은 타입 반환하는 public 메서드 호출이있다 할 수있는 일 :

public class TestDerived : Test<object> 
{ 
} 

public class TestDerivedManager : ITesting<object> 
{ 
    public TestDerived LoadTest() 
    { 
    return new TestDerived(); 
    } 

    Test<object> ITesting<object>.LoadTest() 
    { 
    return this.LoadTest(); 
    } 
} 

을 그 구현에 복잡함을 추가하지만 인터페이스와의 호환성과 함께 사용자가 찾고있는 공개 계약도 제공합니다.

0

누구나 기술적 인 대답이 있지만 아무도 이유를 설명하지 못합니다. 그래서 저는 인터페이스에 대한 예를 보여줄 것이라고 생각합니다.

인터페이스 프로그래밍의 일반적인 방법은 인터페이스에 설명 된 정확한 방법이나 속성을 구현해야한다는 것입니다.

ITesting<object> testingLoader = GetTestingLoader(); 
Test<object> testingLoader.LoadTest(); 

당신이 인터페이스를 사용하여 개체에 액세스하는 경우, 당신은 몰라 :

public interface ITesting<T> 
{ 
    Test<T> LoadTest(); 
} 

같이해야 당신의 소비자에서이 인터페이스의 사용 :의 당신이 인터페이스를 가지고 있다고 가정 해 봅시다 이행. 인터페이스 ITesting<T>LoadTest() 메서드의 경우 Test<T>을 반환한다는 것을 알고 있습니다.

위의 소비자 예제를 보면 의미가 있습니다. 개발자 (및 컴파일러)는 사용자가 선언하지 않는 한 인터페이스 ITesting<object>Test<object> LoadTest() 메서드가 있음을 알지 못합니다. ITesting<object>으로 구현되었지만 Test<object> LoadTest() 메서드가없는 객체를 사용하려고하면 어떻게됩니까? 그렇지 않습니까?

다음은 LSV principle입니다.

+0

Erhm, 아니요, 틀렸어요. LSP에 대해서 말하기 : 나는'TestDerivedManager' 객체를'ITesting '으로 취급하고'LoadTest'를 호출하여'Test '을 얻을 수 있어야합니다. 구현은'TestDerived'를 반환합니다. 이것은'Test '입니다. 그래서 모든 것이 잘되고, LSP 위반도없고, 코드가 작동해야합니다. 오류가 없습니다. 단주의 사항 : 일부 언어는 지원하지만 C#은 지원하지 않습니다. – Virtlink

+0

오, 알았어, 나를 정리 해줘서 고마워. – Fendy

관련 문제