【问题标题】:base class implementing base interface while derived/concrete class implementing extended interface, why?基类实现基接口,而派生/具体类实现扩展接口,为什么?
【发布时间】:2013-09-30 04:12:26
【问题描述】:

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

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

图: http://screencast.com/t/a9UULJVW0

在此图中,

A) IRepository 接口由(抽象基类)RepositoryBase 实现,而

B) IRepository 接口也由接口 ICompanyRepository (ICompanyRepository : IRepository) 扩展。

C) ICompanyRepository 由 CompanyRepository 实现,CompanyRepository 派生自 SQLRepositoryBase,SQLRepositoryBase 派生自 RepositoryBase (; 如 A 点所述,它实现 IRepository,如果 ICompanyRepository 是父级)。

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

ICompanyRepository comRep = new Company Repository();

现在,如果我用 ICompanyRepository 变量 comRep 调用 Add() 函数...

comRep.Add(); 

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

我的问题: 由于调用(abstract-base)类“RepositoryBase”中的函数 Add() 而发生的确切的底层面向对象规则/机制是什么?为方便起见,我在下面说明两种可能的机制:(请告诉我以下两种机制中的哪一种是正确的基础机制)

机制-1 基类“RepositoryBase”中的这个 Add() 函数是否因为“RepositoryBase”实现 IRepository 而被调用? (因此,RepositoryBase 类必须实现 IRepository 才能调用 Add() )

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


我的问题中还有其他内容,我无法理解哪个 OO 规则适用于我的案例,如下所述:

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

类层次结构链中的最后一个派生类“CompanyRepository”实现了 ICompanyRepository(CompanyRepository 没有实现 IRepository 接口的 Add() 函数),而根(最顶层的父)(抽象基)类即 RepositoryBase 实现了 Add() 函数.

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

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

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

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

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

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

【问题讨论】:

  • 你能把它清理一下,让它更容易阅读吗?
  • 罗伯特,现在好些了吗?

标签: c# oop inheritance interface interface-implementation


【解决方案1】:

这是很多话。我将重申我认为你在问的问题并回答这个问题。如果我不正确,请告诉我。

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

是的,这称为“接口重新实现”,它改变了方法的映射方式。 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() 方法,所以要检查它的父类。
  • SQLRepositoryBase 被检查,并没有直接实现方法,所以它的父类被检查。
  • RepositoryBase 被检查并且它确实实现了该方法,所以这就是将被调用的方法。

【讨论】:

  • 克里斯,我的问题中可能需要解释的其他内容很少。我将在您上面提到的答案和代码以及相关的 OO 规则(指定接口是查找起点的最派生类型)的上下文中再次提出问题。
  • 我将编辑您上面的代码,所以请在更改代码的上下文中回答。
  • @FakharAnwar 您对问题的更改似乎与您的原始问题相同。我已针对您的情况添加了特定的查找步骤以澄清答案。
  • 太棒了克里斯!这确实回答了我的问题,并且非常合乎逻辑和精确。我不知道如何将您的答案评为最佳。 :)
  • @FakharAnwar 这是您可以做的quick overview。很高兴答案有所帮助。
猜你喜欢
  • 2010-09-22
  • 2014-06-17
  • 2016-07-22
  • 2012-05-14
  • 2012-03-14
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
相关资源
最近更新 更多