私は共分散とLSPを理解しようとしています。 this questionから、C#は戻り型共分散をサポートしていないことがわかります。しかし、Liskov substitution principleは戻り値型に共分散を課します。C#リターン型共分散とリスコフ置換の原理
この原則をC#で適用することは不可能ですか?それとも私は何かを忘れてしまったのか?
私は共分散とLSPを理解しようとしています。 this questionから、C#は戻り型共分散をサポートしていないことがわかります。しかし、Liskov substitution principleは戻り値型に共分散を課します。C#リターン型共分散とリスコフ置換の原理
この原則をC#で適用することは不可能ですか?それとも私は何かを忘れてしまったのか?
C#はまだリスコフの置換原則を適用することができます。
良いソースは、C#でS.O.L.I.Dの原則のこの話です。
は考えてみましょう:
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();
}
}
をC#は、その後Base2
でMethod()
のオーバーライドは以下のようなものを宣言することができ、共変戻り値の型をサポートしている場合:
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)
サポートは限られています。これは、インターフェイスでのみ機能するためです。受け入れ答え書き換えること:この場合
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();
}
}
をDerived2
はBase2<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