Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing Interfaces That "Inherit" (Implement) A Common Interface?

interface ITurtle
{        
    void Fight();
    void EatPizza();
}

interface ILeonardo : ITurtle
{
    void UseKatana();
}

interface IRaphael : ITurtle
{
    void UseSai();
}

interface IDonatello : ITurtle
{
    void UseBo();
}

interface IMichelangelo : ITurtle
{
    void UseNunchuku();
}

What if I want to create a grand turtle that can do all 4? I want to code:

class GrandTurtle : IMichelangelo, IDonatello, IRaphael, ILeonardo
{
    // Implementation not shown for brevity.
}

Is this possible because now, it seems like I'd have to implement Fight() and EatPizza() 4 times each. But I think those two common functions will resolve and would only need to be implemented once, right?

I could have created the 4 intermediate interfaces without inheriting ITurtle, and then have GrandTurtle implement ITurtle. This solves the interface inheritance issue but now it looks semantically wrong because it makes ITurtle look like a 5th brother which it's not. Plus, I want to be able to create turtle-specific classes, for example, class BostonLeonardo : ILeonardo.

I've read from many places and it seems like an endless debate - some say "inheritance within interfaces" is perflectly fine, and those that say it's not - either I don't understand their explanation or they just say it's bad practice without explaining why.

like image 860
Mickael Caruso Avatar asked Mar 21 '23 20:03

Mickael Caruso


1 Answers

You can only implement the methods Fight and EatPizza once because only one of the interfaces defines them. If you had Fight and EatPizza on each of the ILeonardo etc. interfaces, you could choose to implement them once OR use explicit interface implementations to change the behavior of those methods per interface signature. I'll do an example because I love TMNT:

interface ILeonardo
{
    void Fight();
    void EatPizza();
    void UseKatana();
}

interface IRaphael
{
    void Fight();
    void EatPizza(); 
    void UseSai();
}

interface IDonatello
{
    void Fight();
    void EatPizza();
    void UseBo();
}

interface IMichelangelo
{
    void Fight();
    void EatPizza();
    void UseNunchuku();
}

class GrandTurtle : IMichelangelo, IDonatello, IRaphael, ILeonardo
{
    // Code that fires when Fight is called on ILeonardo turtle = new GrandTurtle()
    void ILeonardo.Fight()
    {
        UseKatana();
    }

    // Code that fires when Fight is called on IRaphael turtle = new GrandTurtle()
    void IRaphael.Fight()
    {
        UseSai();
    }

    // Code that fires for all other turtles
    public void Fight()
    {
        UseThatCrappyStickThingTheOldActionFiguresCameWith();
    }

    // Implement EatPizza() and such here...
}

These explicit interface implementations would take effect only when the type signature of GrandTurtle is the appropriate interface.

like image 102
Haney Avatar answered Apr 06 '23 00:04

Haney