2017-05-10 1 views
4

공역과 LSP를 이해하려고합니다. this question에서 C#은 반환 유형 공분산을 지원하지 않음을 알 수 있습니다. 그러나 Liskov substitution principle은 반환 유형에 공분산을 적용합니다.C# 반환 형식 공분산 및 Liskov 대체 원칙

C#에서이 원칙을 적용하는 것이 불가능하다는 뜻입니까? 아니면 내가 뭔가를 이해하지 못 했니?

+2

당신은 오해를. 반환 유형 공분산은 반환 값이 공변수와 동일한 것은 아닙니다. 이는 다른 반환 유형으로 메소드를 재정의 할 수 없다는 것을 의미합니다. 기본 유형을 반환하는 메소드에서 파생 된 유형의 인스턴스를 반환하는 것은 여전히 ​​완벽하게 완벽합니다. 파생 유형은 여전히 ​​기본 유형의 부속 유형입니다. LSP는 여전히 잘 맞습니다. – Luaan

답변

4

C#을 여전히 Liskov 대체 원칙을 적용 할 수

좋은 소스는 C#에서 S.O.L.I.D 원칙의 이야기입니다. C#을 다음 Base2에서 Method()에 대한 재정의 thusly 히 선언 할 수 공변 반환 형식, 지원

public class Base1 
{ 
} 

public class Derived1 : Base1 
{ 
} 

public class Base2 
{ 
    public virtual Base1 Method() 
    { 
     return new Base1(); 
    } 
} 

public class Derived2 : Base2 
{ 
    public override Base1 Method() 
    { 
     return new Derived1(); 
    } 
} 

경우 :

고려

public class Derived2 : Base2 
{ 
    public override Derived1 Method() 
    { 
     return new Derived1(); 
    } 
} 

C 번호는 이것을 허용하지 않습니다, 당신은을 선언해야합니다 반환 유형은 기본 클래스에있는 것과 동일합니다 (즉, Base1).

그러나 이렇게해도 Liskov 대체 원칙을 위반하지 않습니다.

이를 고려

Base2 test = new Base2(); 
Base1 item = test.Method(); 

비교 :

Base2 test = new Derived2(); 
Base1 item = test.Method(); 

우리는 완전히 문제없이 new Derived2()new Base2()을 대체 할 수 있습니다. 이것은 Liskov 대체 원칙을 준수합니다.

0

C#은 제네릭과 out 일반 수정자를 통해이 기능을 제한적으로 지원합니다. (https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out-generic-modifier)

지원은 인터페이스에서만 작동하므로 제한적입니다. 단지 Base2<Derived1>를 구현하지 않습니다이 경우 Derived2에서

public class Base1 
{ 
} 

public class Derived1 : Base1 
{ 
} 

public interface Base2<out T> where T : Base1 
{ 
    T Method(); 
} 

public class Derived2 : Base2<Derived1> 
{ 
    public Derived1 Method() 
    { 
     return new Derived1(); 
    } 
} 

뿐만 아니라 Base2<Base1>을 구현하는 것입니다 : 허용 대답을 다시 작성합니다. 당신이 Base2<Base1> 인터페이스를 통해 Method를 호출하는 경우가 Base1 반환 형식을 가지고 있기 때문에

원칙이 적용됩니다,하지만 당신은 Derived2를 통해 호출하는 경우는 Derived1 반환 형식이있을 것이다. 이 원칙을 위반 할 수없는 것을, https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/in-generic-modifier

참고 :

마찬가지로 당신은 in 일반적인 수정과 매개 변수 contravariance을 구현할 수 있습니다.위의 예에서 당신이 in 키워드에 out 키워드를 변경하는 경우, 소스는 컴파일되지 않습니다, 다음과 같은 오류를 얻을 것이다 :

Error CS1961 Invalid variance: The type parameter 'T' must be covariantly valid on 'Base2<T>.Method()'. 'T' is contravariant. 
관련 문제