0

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; }   
}
2
  • Go back an review GEOMETRY, Inherited classes are like sets and subsets but doesn't allow multiple inheritance. So you need a common Airplane class with two inherited classes AirBus and Boeing. Then a class for engines with two types GE and PrattWhitney. Commented Jul 31, 2022 at 10:08
  • To be honest, these are just aarbitrary names. Commented Jul 31, 2022 at 15:50

2 Answers 2

3

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 { ... } 
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

thank you very much. Now I understand It, I just have a small question. In the second situation IAirbus hides impl from IBoeing, doesn't that mean, that, in that case, the PrattWhitney implements the impl only from IAirbus, as opposed to the First situation where PrattWhitney implements the impl from both IAirbus and IBoeing?
@Jason9789 no, “hiding” just means that if you access impl through IAirbus, you will not be access IBoeing.impl, you will only get IAirbus.impl. Though in this case, both properties have the same implementation, so there is not much difference anyway. In cases like the last 2 code snippets, where the two interface members are implemented differently, you can see a difference. ((IBoeing)x).impl and `((IAirbus)x).impl‘ are different.
@Jason9789 bottom line is, hiding is about member lookup (what a name means), not interface mapping (which method implements a given interface method). These are different processes that the compiler does.
1

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://learn.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
}

Comments

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.