协方差和协方差是否也意味着使用同一类型?

时间:2018-10-07 21:15:19

标签: c# oop inheritance types subtyping

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

  

自变量的一致性。 m1 m2 的数量相同   论点。如果 m1 的参数类型列表是 a ,而 m2 的参数类型列表   是 b ,然后是∀i。 a i < b i //表示 a b 。

从另一本教材中:

  

对于功能类型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?那是雇员的财产,但必然是人的财产。

1 个答案:

答案 0 :(得分:0)

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#
}

您是正确的。如果您希望将GetJobTitle中的DervierRegister中的override视为GetJobTitlePersonRegister的{​​{1}},则它必须使用完全相同的 类型。应该允许以书面形式创建此方法,但是它会遮盖来自PersonRegister的那个方法,并且不应将其视为替代。因此,您可以编写以上内容,但是

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

将从PersonRegister调用该方法。

  

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

在无法普遍使用协方差和对数的情况下,是的。但是,对于通用interfaces and delegates,在C#4.0中添加了支持。而且,正如讨论的那样,当正式讲话时,每种类型都被视为自身的子类型,因此诸如“ a a 的子类型”之类的短语对所有类型均成立< em> a 。