基类实现基接口,而派生/具体类实现扩展接口,为什么

本文关键字:接口 实现 扩展 为什么 派生 基类 | 更新日期: 2023-09-27 18:32:34

我正在关注一本名为".NET Domain Driven Design with C#"的书。

问题基于场景,如下面的类图所示:

数字:http://screencast.com/t/a9UULJVW0

在此图中,

A( IRepository 接口由(抽象基类(存储库库实现,而

B( IRepository接口也由接口ICompanyRepository

(ICompanyRepository IRepository(扩展。

C( ICompanyRepository 由 CompanyRepository 实现,它派生自 SQLRepositoryBase,

而 SQLRepositoryBase 派生自 RepositoryBase(;如 A 点所述,如果 ICompanyRepository,则实现父级 IRepository(。

D( 我创建了一个接口 ICompanyRepository 的变量,它引用了 clas CompanyRepository 的对象,如下所示:

ICompanyRepository comRep = new Company Repository();

现在,如果我使用 ICompanyRepository 变量 comRep...

comRep.Add(); 

然后调用 RepositoryBase 类(它是 CompanyRepository 的父级(中的 Add(( 函数。

我的问题:究竟是什么底层的面向对象规则/机制,因此调用(抽象基础(类"RepositoryBase"中的函数Add((?为了方便起见,我在下面陈述了两种可能的机制:(请告诉我下面陈述的两种机制中的哪一种是正确的底层机制(

机制-1调用基类"RepositoryBase"中的这个Add((函数是因为"RepositoryBase"实现了IRepoitory吗?(因此,RepositoryBase 类必须实现 IRepository 才能调用 Add(( (

机制-2:调用基类"RepositoryBase"中的 Add(( 函数是因为 CompanyRepository 实现了 ICompanyRepository,它实现了包含 Add(( 函数定义的 IRepository,这样当 Add(( 函数在 ICompanyRepository 上调用(变量(时,它首先在 ICompanyRepository 中找到 Add 的定义,然后在父接口 IRepository 中找到 Add(( 的定义,然后跳转到 CompanyRepository 类以查找 Add(( 函数的实现,但找不到 Add(( 的定义 函数它向上遍历到父类 SQLRepositoryBase 以查找 Add(( 函数等,并且当它在 RepositoryBase 类中找到函数 Add(( 时,它会在 RepositoryBase 中调用 Add(( 函数。这意味着,如果它在 RepositoryBase 的任何派生类中找到 Add(( 函数,它就不会进一步向上遍历(在父类中(。所有这些也意味着,为了在类链中从派生类遍历到父类只是为了找到 Add(( 函数,RepositoryBase 类真的不需要直接从 IRepository 继承吗?


的问题中还有其他事情,我无法理解哪种 OO-Rule 适用于我的情况,如下所述:

在我的问题中,有两个接口,一个是父接口,即IRepository,另一个是扩展它,即ICompanyRepository。父接口 IRepository 包含 Add(( 函数的设计,但不包含子接口 ICopmanyRepository。

层次结构链中的最后一个派生类"CompanyRepository"实现了ICompanyRepository(CompanyRepository不实现IRepository接口的Add((函数(,而root(最顶层父级((抽象基础(类即RepositoryBase实现了Add((函数。

所以结构就像 http://screencast.com/t/a9UULJVW0 中显示的图像一样。

现在,如果我调用Add((函数:

code ICompanyRepository lastDerived = new CompanyRepository((;ICompanyRepository->Add((;code

然后,根据您在回答中陈述的 OO-规则,查找将从 CompanyRepository 类开始,期望 CompanyRepository 将实现 Add(( 函数为 code IRepository.Add(( {}//从 [link] 中的 P17 和 P18 推导 http://www.codeproject.com/Articles/18743/Interfaces-in-C-For-Beginners[link] code

但是,在我的案例中,类 CompanyRepository 没有实现 IRepository.Add(( { },尽管控制流(跟踪时(成功跳转到基类中的 Add(( 函数(并且代码工作正常(。我无法理解此处应用哪个 OO-规则?

如果您需要我用代码显示上述场景,请告诉我。

基类实现基接口,而派生/具体类实现扩展接口,为什么

这是很多词。我将重申我认为你在问什么,并回答这个问题。如果我偏离了目标,请告诉我。

通过接口调用方法时,是否重要 接口再次显式声明为在派生类型上实现 在类型层次结构中?

是的,这称为"接口重新实现",它改变了方法的映射方式。C# 语言规范(第 13.4.6 节 接口重新实现(对此进行了更详细的介绍,但要点是指定接口的派生类型是查找的起点。

interface ICreature
{
    void Speak();
}
class Animal : ICreature
{
    public void Speak() { Console.WriteLine("Rawr"); }
}
class Duck:Animal
{
    public void Speak() { Console.WriteLine("Quack"); }
}
class Human : Animal, ICreature
{
    public void Speak() { Console.WriteLine("Hello"); }
}

如果您执行以下操作,它将打印出"Rawr"和"Hello"。

ICreature duck = new Duck();
ICreature human = new Human();
duck.Speak();
human.Speak();

这是因为在 Duck 层次结构中,指定 ICreature 接口的最派生类型是 Animal,因此它将打印出"Rawr"。

在 Human 层次结构中,指定 ICreature 接口的最派生类型是 Human(Human声明一个实现(,因此它将打印出"Hello"。如果 Human 类型没有声明实现,它也会打印"Rawr"。

更新

在您的特定情况下,适用完全相同的规则。让我们逐步完成这些步骤。

  • ICompanyRepository 继承自 IRepository
  • CompanyRepository 声明它实现了 ICompanyRepository
  • CompanyRepository 现在隐式地重新声明它实现了 IRepository,因为 ICompanyRepository 继承自 IRepository

然后,调用链遵循以下步骤。

  • Add() 方法通过键入到 ICompanyRepository 接口的实例调用。
  • 显式声明它实现 IRepository 的最派生类型现在是 CompanyRepository,因此查找从那里开始。
  • CompanyRepository 不直接实现 Add(( 方法,因此会检查其父类。
  • SQL 实例库被检查,并且不直接实现该方法,因此检查其父类。
  • RepositoryBase 被检查,它确实实现了该方法,因此这就是将被调用的方法。