Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 structs)

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 interfaces by separating them from interfaces 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.

like image 301
ajlane Avatar asked Feb 05 '09 14:02

ajlane


People also ask

Can we have protected member in interface?

In general, the protected members can be accessed in the same class or, the class inheriting it. But, we do not inherit an interface we will implement it. Therefore, the members of an interface cannot be protected.

Why interface Cannot have protected methods?

Protected methods are intended for sharing implementation with subclasses. Interfaces have nothing to offer as far as implementation sharing goes, because they have no implementation at all. Therefore all methods on interfaces must be public.

Can we declare interface members as private or protected?

Protected fields of an interface In general, the protected fields can be accessed in the same class or, the class inheriting it. But, we do not inherit an interface we will implement it. Therefore, cannot declare the fields of an interface protected.

Can we define protected members in interface C#?

An interface cannot include private, protected, or internal members. An interface cannot contain fields. By default, all the members of an interface are public and abstract. C# will give a compile-time error if used 'public' keyword explicitly.


1 Answers

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.

like image 182
Szymon Rozga Avatar answered Oct 23 '22 21:10

Szymon Rozga