Home > Blockchain >  Class implementing two interfaces with the same abstract method C#
Class implementing two interfaces with the same abstract method C#

Time:08-01

Here I have two situations:

  • First situation: class PrattWhitney implements two separate interfaces: IBoeing and IAirbus

  • Second situation: class PrattWhitney implements IBoeing and IAirbus and IArbus inherits IBoeing

I both cases I have an auto-implemented property impl in both interfaces.

In the first situation, which interface does the PrattWhitney.impl property implement - IBoeing or IAirbus?

And in the second situation, which interface does the PrattWhitney.impl property implement - IBoeing or IAirbus?

First situation:

interface IBoeing 
{
    int impl { get; set; }
}

interface IAirbus 
{
    int impl { get; set; }
}

class PrattWhitney : IBoeing, IAirbus  
{
    public int impl { get; set; }   
}

Second situation:

interface IBoeing 
{
    int impl { get; set; }
}

interface IAirbus : IBoeing 
{
    int impl { get; set; }
}

class PrattWhitney : IBoeing, IAirbus 
{
    public int impl { get; set; }   
}

CodePudding user response:

In both cases, PrattWhitney.impl implements the impl declared in both interfaces.

You can reason about it this way:

  • you wrote class PrattWhitney : IBoeing, IAirbus
  • you wrote only one property called impl
  • class PrattWhitney : IBoeing, IAirbus wouldn't compile if PrattWhitney doesn't actually implement both of those interfaces
  • your code compiles
  • therefore the single property you wrote must have matched both IBoeing.impl and IAirbus.impl

As specified in the language spec,

A class or struct shall provide implementations of all members of the interfaces that are listed in the base class list of the class or struct. The process of locating implementations of interface members in an implementing class or struct is known as interface mapping.

Interface mapping for a class or struct C locates an implementation for each member of each interface specified in the base class list of C. The implementation of a particular interface member I.M, where I is the interface in which the member M is declared, is determined by examining each class or struct S, starting with C and repeating for each successive base class of C, until a match is located:

[...]

The language is designed to go over each interface member, and look for an implementation for each of them, rather than go over the members of the class, and look for an interface member for it to implement. It also doesn't matter if the implementation is already used to implement another interface member. Therefore, it can find the same PrattWhitney.impl to implement both IBoeing.impl and IAirbus.impl.

I should mention that the additional inheritance in the second situation doesn't change anything substantial in the context of your question - you still have IBoeing.impl and IAirbus.impl, and PrattWhitney.impl implements both for the same reason. Note that the impl declared in IAirBus hides the inherited impl, as specified here.

The inherited members of an interface are specifically not part of the declaration space of the interface. Thus, an interface is allowed to declare a member with the same name or signature as an inherited member. When this occurs, the derived interface member is said to hide the base interface member. Hiding an inherited member is not considered an error, but it does cause the compiler to issue a warning. To suppress the warning, the declaration of the derived interface member shall include a new modifier to indicate that the derived member is intended to hide the base member. This topic is discussed further in §7.7.2.3.

Though I don't see why something called PrattWhitney should implement something called IBoeing and IAirBus, if you would like different implementations for the interfaces, you can use explicit interface implementations:

class PrattWhitney : IBoeing, IAirbus {

    int IAirbus.impl { 
        get { ... } 
        set { ... } 
    }

    int IBoeing.impl { 
        get { ... } 
        set { ... } 
    }
}

This will make it not possible to access impl on an expression of type PrattWhitney. If you want to do that, you can make one of them an implicit implementation:

class PrattWhitney : IBoeing, IAirbus {

    int IAirbus.impl { 
        get { ... } 
        set { ... } 
    }

    public int impl { 
        get { ... } 
        set { ... } 
    }
}

CodePudding user response:

First situation:

class PrattWhitney : IBoeing, IAirbus  
{
//  This property implements both `IAirbus.impl` and `IBoeing.impl`.
    public int impl { get; set; }   
}

Second situation:

interface IBoeing 
{
    int impl { get; set; }
}

interface IAirbus : IBoeing 
{
//  / The missing "new" keyword is treated as warning.
//  | See: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/knowing-when-to-use-override-and-new-keywords
//  V
    new int impl { get; set; }
}

class PrattWhitney : IBoeing, IAirbus 
{
//  This property implements both `IAirbus.impl` and `IBoeing.impl`.
    public int impl { get; set; }   
}

If you want implement property/method with same signature but from different interfaces you can explicitly implement them (see docs).

class PartWhitney : IBoeing, IAirbus {
   int IAirbus.impl { get; set; } = 5

   int IBoeing.impl { get; set; } = 7
}
  • Related