嵌套协方差会变成逆方差吗?



我将协方差和CotraVariance的概念理解为,当接口需要标记为只读时,我们使用T,对于只写接口,我们在T中使用,以便确保类型安全而不是获取和设置对象的东西。但是当我们嵌套这些时,逆方差如何被视为协方差。例如:

interface IObservable<out T>
{
IDisposable Subscribe(IObserver<T> o);
}
interface IObserver<in T>
{
void OnNext(T t);
void OnError(Exception e);
void OnCompleted();
}

请用一个例子来解释嵌套的东西是如何改变它们的方差的。 或者请把我重定向到一个好的阅读材料。提前谢谢。

让我们为引用类型的"is a"关系编写(一种修改后的小于符号)。例如Elephant ⊂ IMammalIMammal ⊂ IAnimal

先看IObserver<>

interface IObserver<in T>
{
void OnNext(T t);
// other members irrelevant
}

"in"意味着它是逆变的。逆变意味着:

如果X ⊂ Y,则IObserver<Y> ⊂ IObserver<X>

相反,是因为当您"在的两侧应用IObserver<·>"时,XY的顺序会发生变化。这类似于将不等式(来自数学)乘以两边的数。你必须交换不平等的两面(或将变成)。

之所以允许在T中具有IObserver<T>逆变T是因为 仅用于方法(即OnNext)中的值参数。

假设我们有一个IObserver<IMammal>的实例。这可以在其OnNext(IMammal t)方法中采用任何IMammal。此实例也可以充当IObserver<Elephant>?是的,因为如果它可以接受任何IMmammal,那么特别是它可以接受Elephant,所以逆变是安然无恙的。因为Elephant"是一个"IMammal,那么IObserver<IMammal>"是一个"IObserver<Elephant>

逆变颠倒了关系。

现在,让我们看看另一种类型(现在我们来问你问什么!我将其从IObservable<>重命名为IVable<>

interface IVable<out T>
{
IDisposable Subscribe(IObserver<T> o);
}

"出"表示协变。协变意味着:

如果X ⊂ Y,则IVable<X> ⊂ IVable<Y>

这就像在数学中,当你把不等式的两边都乘以一个正数时。XY不交换 (co-)。

但是,当IVable<T>有一个方法时,它怎么可能是协变的,Subscribe,它接受"有T的东西"?那是因为那个"东西"在T是逆变的!

让我们看看它是否安然无恙。因此,假设我们有一个实例,该实例是IVable<IMammal>.这意味着它有一个可以接受任何IObserver<IMammal>Subscribe.但后者是逆变的,所以因为IMammal"是"IAnimal,所以任何IObserver<IAnimal>"是"IObserver<IMammal>。因此,这表明我们的IVable<IMammal>可以充当协方差所指示的IVable<IAnimal>。所以一切都很好。

结论:在T中"输入"的东西,就像在T中"退出"一样。同样,发送"出"的东西在T中是逆变的,就像T中的"进"。

相关内容

  • 没有找到相关文章

最新更新