Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am following a book namely ".NET Domain Driven Design with C#".

Question is based on scenario as shown in Class Diagram below:

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

In this diagram,

A) IRepository interface is implemented by (abstract base class) RepositoryBase whereas,

B) IRepository interface is also extended by interface ICompanyRepository (ICompanyRepository : IRepository).

C) ICompanyRepository is implemented by CompanyRepository which is derived from SQLRepositoryBase which is derived from RepositoryBase (; which, as stated in point A), implements IRepository which is parent if ICompanyRepository).

D) i create a variable of interface ICompanyRepository having reference to object of clas CompanyRepository, like below:

ICompanyRepository comRep = new Company Repository();

Now, if i call Add() function with ICompanyRepository variable comRep...

comRep.Add(); 

then Add() function in RepositoryBase class (which is parent of CompanyRepository) is called.

My Question: What is the exact underlying Object Oriented Rule/Mechanism takes place due to which the function Add() in (abstract-base) class "RepositoryBase" is called? For convenience i am stating below two possible mechanisms: (please tell me which one of two stated below is correct underlying mechanism)

Mechanism-1 Is this Add() function in base class "RepositoryBase" is called because "RepositoryBase" implements IRepoitory ? (Hence making it mandatory for RepositoryBase class to implement IRepository in order to call Add() )

OR

Mechanism-2: The Add() function in base class "RepositoryBase" is called because CompanyRepository implements ICompanyRepository which implements IRepository which contains definition for Add() function such that when Add() function is called on (with variable of) ICompanyRepository then it first finds the definition of Add in ICompanyRepository and then in parent interface IRepository and then jumps to CompanyRepository class to find implementation of Add() function and not finding the definition of Add() function it traverse upward to parent class SQLRepositoryBase to find Add() function and so on, and as it finds the function Add() in RepositoryBase class so it calls the Add() function in RepositoryBase. This means that if it would have found the Add() function in any of derived classes of RepositoryBase, it had not traverse further upward (in parent class). All of this also means that , in order to traverse from derived class to parent class in chain of classes just to find Add() function, the RepositoryBase class does not really need to inherit directly from IRepository?


There are additional thing in my question and i am unable to understand which OO-Rule is applying in my case as stated below:

In my Question there are two Interfaces one is parent namely IRepository and other is extending it namely ICompanyRepository. Parent interface IRepository contains deifinition of Add() function but not the child interface ICopmanyRepository.

Last derived class in the chain of class Hierarchy "CompanyRepository" implements ICompanyRepository (CompanyRepository does not implement Add() function of IRepository interface) whereas root (top most parent) (abstract base) class namely RepositoryBase implements the Add() function.

So the structure is like the image shown in http://screencast.com/t/a9UULJVW0.

Now if i call Add() function:

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

Then according to the OO-Rule you stated in you answer, the lookup will start from CompanyRepository class with expectation that CompanyRepository would have implemented Add() function as code IRepository.Add() { } //deduced from P17 and P18 in [link] http://www.codeproject.com/Articles/18743/Interfaces-in-C-For-Beginners[link]code

BUT, in my case class CompanyRepository does not have implementation IRepository.Add() { } although the flow of control (while tracing) jumps to Add() function in base class successfully (And code is working fine). I am unable to understand which OO-Rule is applying here ?

Please let me know if you need me to show above scenario with code.

like image 467
Fakhar Anwar Avatar asked Sep 24 '13 19:09

Fakhar Anwar


1 Answers

That's a lot of words. I'm going to restate what I think you're asking and answer that question instead. If I'm off the mark, let me know.

When invoking a method through an interface, does it matter if that interface is explicitly declared again as being implemented on a more derived type in the type hierarchy?

Yes, this is called "interface re-implementation" and it changes how the method is mapped. The C# language specification (Section 13.4.6 Interface Re-Implementation) goes into this in a little bit more detail, but the gist is that the most derived type that specifies that interface is the starting point for lookup.

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"); }
}

If you do the following, it will print out "Rawr" and "Hello".

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

This is because in the Duck hierarchy, the most derived type specifying the ICreature interface is Animal and so it will print out "Rawr".

In the Human hierarchy, the most derived type specifying the ICreature interface is Human (and Human declares an implementation) and so it will print out "Hello". If the Human type had not declared an implementation, it would also have printed "Rawr".

Update

In your specific case, the exact same rule applies. Let's walk through the steps.

  • ICompanyRepository inherits from IRepository
  • CompanyRepository declares that it implements ICompanyRepository
  • CompanyRepository has now implicitly redeclared that it implements IRepository because ICompanyRepository inherits from IRepository

The call chain then follows these steps.

  • The Add() method is called through the instance typed to the ICompanyRepository interface.
  • The most derived type that has explicitly declared that it implements IRepository is now CompanyRepository, so lookup begins there.
  • CompanyRepository does not implement the Add() method directly, so its parent class is inspected.
  • SQLRepositoryBase is inspected and does not directly implement the method, so its parent class is inspected.
  • RepositoryBase is inspected and it does implement the method, so that is the method that will be called.
like image 142
Chris Hannon Avatar answered Oct 14 '22 20:10

Chris Hannon