【问题标题】:Does contravariance and covariance means using also the same type?逆变和协方差是否意味着也使用相同的类型?
【发布时间】:2019-03-12 13:51:02
【问题描述】:

我很困惑。我偶然发现了签名规则(B.Liskov 在她的作品中也提到过),其中指出:

论点的逆变性。 m1m2 的数量相同 论据。如果m1的参数类型列表是am2b,然后是 ∀i 。 ai bi //表示ab.

来自其他教材:

对于函数类型 DY→CY 成为(即,可替代)的子类型 DX→CX ,我们必须在结果类型上是协变的,但在 参数类型!

那么,如果我只使用相同类型的参数和返回类型,这是否意味着我永远不会进行正确的子类型化?我不明白使用相同类型是否也很重要,即当我对父类和子类方法参数使用相同类型时,这是逆变的吗?

换句话说,由于 c# 不允许参数逆变,这是否意味着我的代码从不兼容 LSP?当我读到 LSP 要求参数必须是逆变的..

class Person
{
}
class Employee: Person
{
}

class PersonRegister
{
   GetJobTitle(Employee e) {return e.JobTitle;}
}

class DeriverRegister: PersonRegister
{
  GetJobTitle(Person p)  //contravariance, using less derived type, cannot be done in C#
}

如果例如,这将如何工作较少派生的类型没有所需的字段,在此示例中是 JobTitle?这是 Employee 的财产,但必须是 Person 的财产。

【问题讨论】:

  • “我不明白是否使用相同的类型也很重要” - 在大多数正式的上下文中,如果 a 和 b 是相同的类型,“a 是 b 的子类型”是正确的,如果那是你的在问?当我们希望排除 a 和 b 是同一类型时,可以使用短语“strict subtype”。
  • @Damien_The_Unbeliever 基本上是的。 LSP 的指导方针说参数必须是逆变的。这是否意味着在父母和孩子中使用相同的类型是令人满意的并且符合要求?
  • 如果您在方法定义中声明了param1 的类型,那么您使用GetJobTitle(param1) 的示例会更有帮助。
  • @JohnWu 好的,定义的类型将是 Employee,因此 Person 是较少派生的类型,因此根据逆变规则是合法的。

标签: c# oop inheritance types subtyping


【解决方案1】:
class Person
{
}
class Employee: Person
{
}

class PersonRegister
{
   GetJobTitle(Employee e) {return e.JobTitle;}
}

class DeriverRegister: PersonRegister
{
  GetJobTitle(Person p)  //contravariance, using less derived type, cannot be done in C#
}

你是对的。如果您希望将DervierRegister 中的GetJobTitle 视为GetJobTitle 中的overridePersonRegister,它必须使用完全相同 相同的类型。您应该允许按照所写的方式创建此方法,但它隐藏来自PersonRegister 的方法,并且不被视为覆盖。所以你可以写上面的,但是

var e = new Employee();
PersonRegister pr = new DervierRegister();
pr.GetJobTitle(e);

将调用来自PersonRegister的方法。

这是否意味着我的代码永远不符合 LSP?

在你不能使用协变和逆变一般的范围内,是的。但是,对于通用 interfaces and delegates,在 C# 4.0 中添加了支持。而且,正如所讨论的,当正式发言时,每种类型都被认为是其自身的子类型,因此诸如“a is subtype of a”这样的短语对所有类型都是正确的一个。

【讨论】:

  • 这就是我不明白的——为什么说参数需要逆变才能进行正确的子类型化?如果较少派生的类型包含较少的信息,它如何工作?
  • @JohnV - 你有链接到你在问题中引用的材料吗?我觉得我错过了一些周围的背景,而且它们本身都没有提到“正确的子类型[ing]”。
  • 当然。第一个直接来自 Barbara Liskov 和 J.Wing 的著名论文:cs.cmu.edu/~wing/publications/LiskovWing94.pdfsee at 1827(签名规则)
  • @JohnV - 好的,所以如果我们接受 C# 的规则比该论文中概述的规则更严格,特别是 C# 的一般语言规则声明i 和 bi 必须是相同的类型(同样适用于返回类型),协变和逆变规则都一般得到满足.
  • 我很难理解为什么参数应该是逆变的。如果基类在其方法中使用 Employee 对象,如果 Person 的数据较少,它如何与派生类覆盖中的 Person 对象一起使用?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-21
  • 1970-01-01
  • 1970-01-01
  • 2011-04-06
  • 1970-01-01
  • 2015-12-15
相关资源
最近更新 更多