Why Can't I Have Protected Interface Members

Why can't I have protected interface members?

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.

In C# can we ever use protected access modifier for an interface?

You can change this acceccibility.

See this page : https://msdn.microsoft.com/en-us/library/ms173121.aspx.

It's say that "Interfaces declared directly within a namespace can be declared as public or internal and, just like classes and structs, interfaces default to internal access."

Be carefull, as you see in this link https://msdn.microsoft.com/en-us/library/ba0a1yw2.aspx members are public by default and can't be modified.

Why do interface members have no access modifier?

Because Interface is in crude terms 'a view to the outside world' and since it is for the outside world, there is no point making its members protected or private.

Or in other words, it is a contract with the outside world which specifies that class implementing this interface does a certain set of things. So, hiding some part of it doesn't make sense.

However, interfaces themselves can have access specifiers like protected or internal etc. Thus limiting 'the outside world' to a subset of 'the whole outside world'.

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.

C#8.0: Protected properties for interfaces with default implementations

First of all, what do you want to achieve? What should Foo.ReturnAs return? How are you going to use those interfaces?

You can't use ReturnAs in the other interfaces without inheriting from IReturnableAs. Once you inherit from that interface though Foo will have to provide an implementation. When that happens, no matter how you cast Foo you'll always get its own IReturnableAs implementation.

Interfaces aren't abstract classes so there can only be one interface member implementation. You can't access different "default" implementations through different interfaces.

Composite result when accessed through IReturnableAs

If you want to return json or image for the specific interfaces and image;json for Foo overall the best option would be for the interfaces to not inherit from IReturnableAs, and provide their own ReturnAs property :

public interface IReturnableAs {
public String ReturnAs { get; }
}
public interface IReturnableAsImage<T>
{
public String ReturnAs =>"image";

protected String ImageResolution { get; set; }
public T ReturnAsImage(String imageResolution = "large")
{
ImageResolution = imageResolution;
return (T)this;
}
}
public interface IReturnableAsJson<T> {
public String ReturnAs =>"json";

protected Boolean IsPretty { get; set; }
public T ReturnAsJson(Boolean isPretty = false) {
IsPretty = isPretty;
return (T)this;
}
}

public class Foo : IReturnableAsImage<Foo>, IReturnableAsJson<Foo> ,IReturnableAs
{
string IReturnableAs.ReturnAs =>"image;json";

String IReturnableAsImage<Foo>.ImageResolution { get; set; }="3";
Boolean IReturnableAsJson<Foo>.IsPretty { get; set; }=false;
}

The following code :

void Main()
{
var foo=new Foo();
Console.WriteLine(((IReturnableAs)foo).ReturnAs);
Console.WriteLine(((IReturnableAsImage<Foo>)foo).ReturnAs);
Console.WriteLine(((IReturnableAsJson<Foo>)foo).ReturnAs);
}

Prints:

image;json
image
json

I removed the ReturnAs setters since the valid value will always be the same for the same interface.

If you want to create a new class that generates JPGs, eg FooJpg, you can override the default implementation of IReturnableAsImage<T>, eg :

public class FooJpg : IReturnableAsImage<FooJpg>, IReturnableAsJson<FooJpg> ,IReturnableAs
{
string IReturnableAs.ReturnAs =>"jpg;json";

String IReturnableAsImage<FooJpg>.ImageResolution { get; set; }="3";
Boolean IReturnableAsJson<FooJpg>.IsPretty { get; set; }=false;

String IReturnableAsImage<FooJpg>.ReturnAs => "jpg";

}

Same result no matter the interface

If you want Foo.ReturnAs to always return the same value, eg "image;json", you can add a default IReturnAs implementation for single use cases, and override the method for multiple uses :

public interface IReturnableAs {
public String ReturnAs { get; }
}

public interface IReturnableAsImage<T>:IReturnableAs
{
String IReturnableAs.ReturnAs =>"image";

protected String ImageResolution { get; set; }
public T ReturnAsImage(String imageResolution = "large")
{
ImageResolution = imageResolution;
return (T)this;
}
}

public interface IReturnableAsJson<T>:IReturnableAs {
String IReturnableAs.ReturnAs =>"json";

protected Boolean IsPretty { get; set; }
public T ReturnAsJson(Boolean isPretty = false) {
//ReturnAs="json";
IsPretty = isPretty;
return (T)this;
}
}

In this case the IReturnableAsImage, IReturnableAsJson interfaces provide an implementation. For this class :

public class Foo : IReturnableAsImage<Foo>
{
String IReturnableAsImage<Foo>.ImageResolution { get; set; }="3";
}

The following code will print image:

void Main()
{
var foo=new Foo();
Console.WriteLine(((IReturnableAs)foo).ReturnAs);
Console.WriteLine(((IReturnableAsImage<Foo>)foo).ReturnAs);
}

For a class that uses both interfaces, an explicit IReturnableAs implementation is needed:

public class FooMulti : IReturnableAsImage<FooMulti>, IReturnableAsJson<FooMulti> 
{
String IReturnableAs.ReturnAs =>"image;json";

String IReturnableAsImage<FooMulti>.ImageResolution { get; set; }="3";
Boolean IReturnableAsJson<FooMulti>.IsPretty { get; set; }=false;
}

In this case all calls will return image;json :

void Main()
{
var foo=new FooMulti();
Console.WriteLine(((IReturnableAs)foo).ReturnAs);
Console.WriteLine(((IReturnableAsImage<FooMulti>)foo).ReturnAs);
Console.WriteLine(((IReturnableAsJson<FooMulti>)foo).ReturnAs);
}

image;json
image;json
image;json

Protected in Interfaces

Because an interface is supposed to mean "what you can see from outside the class". It would not make sense to add non-public methods.

How can an interface implementation be protected?

It's an explicitly implemented interface event:

event NotifyCollectionChangedEventHandler INotifyCollectionChanged.CollectionChanged
{
add { CollectionChanged += value; }
remove { CollectionChanged -= value; }
}

So it satisfies the requirements of INotifyCollectionChanged, but it isn't publicly visible on the class itself - perfectly valid.

This usually signalizes intent - this is not supposed to be a part of the public interface of the class. However, if you absolutely do want to access this from the outside, you can just do a cast to the interface:

((INotifyCollectionChanged)myCollection).CollectionChanged

Why doesn't Java allow private members in interface?

From the Java Language Spec, (Access Control):

"The Java programming language provides mechanisms for access control,
to prevent the users of a package or class from depending on
unnecessary details of the implementation of that package or class."

Access control is all about hiding implementation details. An interface has no implementation to hide.

Why doesn't Java 8 allow interface members to be private?

Because of time constraints in the implementation.

Private methods were originally within spec, but in an email titled "Some Pullbacks", sent by Brian Goetz to the lambda-spec-experts mailing list back when Java 8 was in development, they were pulled.

We would like to pull back two small features from the JSR-335 feature plan:

  • private methods in interfaces
  • "package modifier" for package-private visibility

The primary reason is resourcing ...

Cannot implement property with protected set from interface

Do it like this

    public interface ISegment
{
INode NodeA { get; protected set; }
INode NodeB { get; protected set; }
public sealed void SetNodeA(INode node) => NodeA = node;
public sealed void SetNodeB(INode node) => NodeB = node;
}

public class MyClass : ISegment
{
private Node _nodeA;
private Node _nodeB;

INode ISegment.NodeA
{
get => _nodeA;
set => _nodeA = value as Node;
}

INode ISegment.NodeB
{
get => _nodeB;
set => _nodeB = value as Node;
}

private void Do(INode node)
{
if(node == NodeA) { } // Error
if(node == _nodeA) { } // Warning "Possibly unintended reference comparison"
if (node == ((ISegment)this).NodeA) { } // OK
}
}

but the Question is, why do you want that? Why protected set?

You can do it like this also. (Not helps here because of default implementation in the interface)


public interface IFoo
{
public string Bar { get; }
}

public class Bubu : IFoo
{
public string Bar { get; protected set; }
}

Update: Edited the code to show more exactly, how to access the properties



Related Topics



Leave a reply



Submit