공역과 LSP를 이해하려고합니다. this question에서 C#은 반환 유형 공분산을 지원하지 않음을 알 수 있습니다. 그러나 Liskov substitution principle은 반환 유형에 공분산을 적용합니다.C# 반환 형식 공분산 및 Liskov 대체 원칙
C#에서이 원칙을 적용하는 것이 불가능하다는 뜻입니까? 아니면 내가 뭔가를 이해하지 못 했니?
공역과 LSP를 이해하려고합니다. this question에서 C#은 반환 유형 공분산을 지원하지 않음을 알 수 있습니다. 그러나 Liskov substitution principle은 반환 유형에 공분산을 적용합니다.C# 반환 형식 공분산 및 Liskov 대체 원칙
C#에서이 원칙을 적용하는 것이 불가능하다는 뜻입니까? 아니면 내가 뭔가를 이해하지 못 했니?
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 대체 원칙을 준수합니다.
C#에서는 반환 형식 공분산이 지원되지 않으므로 반환 형식 공분산과 관련하여 Liskov 원칙을 위반하는 것은 불가능합니다. https://youtu.be/gwIS9cZlrhk?t=1886
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.
당신은 오해를. 반환 유형 공분산은 반환 값이 공변수와 동일한 것은 아닙니다. 이는 다른 반환 유형으로 메소드를 재정의 할 수 없다는 것을 의미합니다. 기본 유형을 반환하는 메소드에서 파생 된 유형의 인스턴스를 반환하는 것은 여전히 완벽하게 완벽합니다. 파생 유형은 여전히 기본 유형의 부속 유형입니다. LSP는 여전히 잘 맞습니다. – Luaan