簡體   English   中英

基類實現基接口而派生/具體類實現擴展接口,為什么?

[英]base class implementing base interface while derived/concrete class implementing extended interface, why?

我正在讀一本書“用.NET編寫的.NET域驅動設計”。

問題基於以下類圖所示的場景:

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

在此圖中,

A)IRepository接口由(抽象基類)RepositoryBase實現,而

B)IRepository接口也由接口ICompanyRepository(ICompanyRepository IRepository)擴展。

C)ICompanyRepository由CompanyRepository實現,它派生自SQLRepositoryBase,它源自RepositoryBase(;如A點所述),實現IRepository,如果是ICompanyRepository則為父級。

D)我創建了一個接口ICompanyRepository的變量,它引用了clas CompanyRepository的對象,如下所示:

ICompanyRepository comRep = new Company Repository();

現在,如果我用ICompanyRepository變量comRep調用Add()函數...

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中找到,然后跳轉到CompanyRepository類以查找Add()函數的實現,而不是找到Add()函數的定義,它將向上遍歷到父類SQLRepositoryBase以查找Add()函數等,並在RepositoryBase類中找到函數Add(),因此它調用RepositoryBase中的Add()函數。 這意味着如果它在RepositoryBase的任何派生類中找到Add()函數,它就不會進一步向上遍歷(在父類中)。 所有這些也意味着,為了從派生類遍歷類鏈中的父類只是為了找到Add()函數,RepositoryBase類真的不需要直接從IRepository繼承嗎?


在我的問題中還有其他的事情,我無法理解在我的案例中適用的OO規則如下所述:

在我的問題中有兩個接口,一個是父級,即IRepository,另一個是擴展它,即ICompanyRepository。 父接口IRepository包含Add()函數的定義,但不包含子接口ICopmanyRepository。

類Hierarchy“CompanyRepository”鏈中的最后派生類實現ICompanyRepository(CompanyRepository不實現IRepository接口的Add()函數)而root(最頂層父)(抽象基礎)類即RepositoryBase實現Add()函數。

所以結構就像http://screencast.com/t/a9UULJVW0中顯示的圖像。

現在,如果我調用Add()函數:

code ICompanyRepository lastDerived = new CompanyRepository(); ICompanyRepository->添加(); 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

然后,調用鏈遵循這些步驟。

  • 通過鍵入ICompanyRepository接口的實例調用Add()方法。
  • 顯式聲明它實現IRepository的派生類型最多的現在是CompanyRepository,因此查找從那里開始。
  • CompanyRepository不直接實現Add()方法,因此檢查其父類。
  • 檢查SQLRepositoryBase並且不直接實現該方法,因此檢查其父類。
  • 檢查RepositoryBase並確實實現了該方法,因此這是將被調用的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM