0

Consider the following interfaces in C#:

public interface IUpgradeable 
{
    public void Upgrade();
}

public interface ISpeedUpgradeable : IUpgradeable
{
    public int GetCurrentSpeed();
}

public interface IDamageUpgradeable : IUpgradeable
{
    public float GetCurrentDamage();
}

And the following class that implements them:

public class SpaceShip : ISpeedUpgradeable, IDamageUpgradeable
{
    public int GetCurrentSpeed() 
    { 
        return 0;
    }

    public float GetCurrentDamage()
    {
        return 0f;
    }

    public void Upgrade()
    {
        //Which Upgrade am I implementing? ISpeedUpgradeable? or IDamageUpgradeable?
    }
}

Since both ISpeedUpgradeable and IDamageUpgradeable both extend IUpgradeable, shouldn't they both have implementations of Upgrade() each? or am I misunderstanding how inheritance in interfaces work?

Charlieface
  • 52,284
  • 6
  • 19
  • 43
Arvin
  • 1,391
  • 4
  • 19
  • 33
  • If a class implements both and you cast it to the base interface, how would you specify which one you want? You can't. Thus, there is one shared implementation. – madreflection Jul 12 '22 at 16:30
  • hmmm right, I think I see what you mean. So there can only be one implementation of `IUpgradeable`. – Arvin Jul 12 '22 at 16:34
  • 2
    Unlike a language like C++, C# does not have multiple inheritance. Every method only occupies one "virtual slot" and can only be overridden in one single way. An interface should be seen more as a template or mask for these virtual slots. You can use explicit implementation to implement methods from different interfaces that would otherwise clash by name, but this still doesn't change the basic rule. Default interface implementations (introduced in C# 8) complicate this story a bit, but in a different way, since the methods stick with the interfaces alone. – Jeroen Mostert Jul 12 '22 at 16:34
  • Does this answer your question? [C# Diamond-Inheritance (Interface Implementation)](https://stackoverflow.com/questions/47209963/c-sharp-diamond-inheritance-interface-implementation) – Charlieface Jul 12 '22 at 22:31
  • This is called diamond inheritance – Charlieface Jul 12 '22 at 22:32

1 Answers1

3

There is only one meaning of IUpgradeable. The fact that multiple interfaces inherit it, and add meaning to themselves doesn't change the meaning of the original interface. Your class simply implements ISpeedUpgradeable, IDamageUpgradeable, and IUpgradeable: it doesn't implement a specific flavor of IUpgradeable.

The Upgrade() method should only mean what it means to the IUpgradeable interface. Think about your business model (or in this case probably a game model): is there an item floating around that "upgrades" anything upgradeable that it comes in contact with? Does upgrading the ship mean upgrading its speed, or damage, or both? If simply calling Upgrade doesn't provide enough information to match the way your business model works, you may need to re-think your interface design.

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
  • 1
    These interfaces don't implement methods, they declare or contain them. This would be a nitpick except that default interface implementations now exist, but those aren't involved here. Interfaces never implement other interfaces either (only classes or structs do that); they inherit from them or extend them. – Jeroen Mostert Jul 12 '22 at 16:43
  • 1
    @JeroenMostert: Not a nitpick at all. That was a good catch. Semantics matter in cases like this. I fixed my wording. Interfaces _inherit_ other interfaces. Classes _implement_ interfaces. And now, to some extent, interfaces _can_ implement methods. – StriplingWarrior Jul 12 '22 at 16:44
  • 1
    Understood, thank you! I suppose I will need to put `UpgradeSpeed()` and `UpgradeDamage()` individually so they can be upgraded separately – Arvin Jul 12 '22 at 17:06
  • 1
    @Arvin: that sounds right. FWIW, if you ever find that you need to have similarly-named methods on different interfaces (`ISpeedUpgradeable.Upgrade()` and `IDamageUpgradeable.Upgrade()`), that's possible via _explicit interface implementation_. I'd still prefer the more descriptive method names, though. – StriplingWarrior Jul 12 '22 at 17:53