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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With