Why can't I have protected interface members?
What is the argument against declaring protected-access members on interfaces? This, for example, is invalid:
public interface IOrange
{
public OrangePeel Peel { get; }
protected OrangePips Seeds { get; }
}
In this example, the interface IOrange
would guarantee that implementors at least provide an OrangePips
instance to their inheritors. If the implementor wanted to, they could expand the scope to full public
:
public class NavelOrange : IOrange
{
public OrangePeel Peel { get { return new OrangePeel(); } }
protected OrangePips Seeds { get { return null; } }
}
public class ValenciaOrange : IOrange
{
public OrangePeel Peel { get { return new OrangePeel(); } }
public OrangePips Seeds { get { return new OrangePips(6); } }
}
The intent of protected
members on interfaces is to provide a support contract for inheritors (sub-classes), for example:
public class SpecialNavelOrange : NavelOrange
{
...
// Having a seed value is useful to me.
OrangePips seeds = this.Seeds;
...
}
(Admittedly, this wouldn't work for struct
s)
I can't see much of a case for private
or internal
modifiers in interfaces, but supporting both public
and protected
modifiers seems perfectly reasonable.
I'm going to try explaining the utility of protected
members on interface
s by separating them from interface
s entirely:
Let's imagine a new C# keyword, support
, to enforce inheritor contracts, so that we declare things as follows:
public support IOrangeSupport
{
OrangePips Seeds { get; }
}
This would allows us to contract classes to provide protected members to their inheritors:
public class NavelOrange : IOrange, IOrangeSupport
{
public OrangePeel Peel { get { return new OrangePeel(); } }
protected OrangePips Seeds { get { return null; } }
}
This is not particularly useful, because classes would already imply this contract by providing the protected
members in the first place.
But then we could also do this:
public interface IOrange : IOrangeSupport
{
...
}
Thereby applying IOrangeSupport
to all classes which implement IOrange
and requiring them to provide particular protected
members - which is not something we can currently do.
I think everyone hammered the point of an interface having only public members, no implementation details. What you are looking for is an abstract class.
public interface IOrange
{
OrangePeel Peel { get; }
}
public abstract class OrangeBase : IOrange
{
protected OrangeBase() {}
protected abstract OrangePips Seeds { get; }
public abstract OrangePeel Peel { get; }
}
public class NavelOrange : OrangeBase
{
public override OrangePeel Peel { get { return new OrangePeel(); } }
protected override OrangePips Seeds { get { return null; } }
}
public class ValenciaOrange : OrangeBase
{
public override OrangePeel Peel { get { return new OrangePeel(); } }
protected override OrangePips Seeds { get { return new OrangePips(6); } }
}
Edit: It is fair to argue that if we have a PlasticOrange that derives from a class Ornament, it can only implement IOrange and not the Seeds protected method. That is fine. An interface by definition is a contract between a caller and an object, not between a class and its subclasses. The abstract class is as close as we come to this concept. And that is fine. What you are essentially proposing is another construct in the language through which we can switch subclasses from one base class to another without breaking the build. To me, this doesn't make sense.
If you are creating a subclass of a class, the subclass is a specialization of the base class. It should be fully aware of any protected members of the base class. But if you suddenly want to switch the base class out, it makes no sense that the subclass should work with any other IOrange.
I suppose you have a fair question, but it seems like a corner case and I don't see any benefit from it to be honest.
Can't see why would one want this. If you want derived class to provide an implementation of a particular method, go for abstract base classes. Interfaces are just that - interfaces. A public contract, nothing else. Think of interface as of specification which describes how should the implementation look to the outside world. A specification for a two-pin plug does not state (at least I assume that) what it's internal structure should be like. It just must be interface-compatible with a plug socket.
(source: made-in-china.com)
Because it makes no sense. An interface is a publicly exposed contract. I am an IThing, therefore I will perform IThing methods if asked. You can't ask an IThing to confirm it performs methods it can't tell you about.
Interfaces exist to allow people to access your class without knowing what the concrete implementation is. It completely divorices the implementation from the data passing contract.
Therefore, everything in an interface must be public. Non-public members are only useful if you have access to the implementation and therefore don't meaningfully contribute to an interface definition.