4
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.

1
  • LOL at the downvote. I'm facing this issue right now with ASP.net Identity's IUserStore hierarchy. Commented Jan 24, 2014 at 4:14

1 Answer 1

7

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.

Sign up to request clarification or add additional context in comments.

4 Comments

BIG HELP! Thank you very much! I haven't seen a good explanation on explicit implementation - why do it, and how it's used.
It's generally a bad idea. You should only use it when you are forced to use two libraries whose code you don't control but whose method signatures match... In other words, if you used 3rd party libs Tmnt.dll and PowerRangers.dll and they both had a Fight method on an interface and one of your classes implemented both interfaces, you'd need to do it.
It works when 2 separate interfaces have the same member, not when shared one comes from parent interface - so you can only have one ITurtle.Fight explicit or implicit.
@AlexeiLevenkov updated to be way more accurate/true. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.