Protected in Interfaces

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.

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.

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.

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

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

Interface cannot declare private / protected functions

Interface describes how to interact with object (public methods).

Interface must know nothing about internal object structure (private or protected methods)

and interface don't care what going on under the hood of object.

Also private and protected methods may be vary depending on low layer implementation.

For example we have interface SocialMedia

interface SocialMedia
{
public function share();
}

And inside this interface we don't care (and don't have to care) about how exactly object will share information, we only know that information will be shared.

And also we have 2 classes:

class Twitter implements SocialMedia
{
private function tweet()
{
}

public function share()
{
return $this->tweet();
}
}

class Facebook implements SocialMedia
{
private function post()
{
}

public function share()
{
return $this->post();
}
}

As you can see this classes implements SocialMedia and we know how to interact with them - exactly this is intention of interface.

Also we have private methods tweet for class Twitter and post for Facebook this methods are low layer implementation inside particular class, so we can not describe such methods inside interface.



Related Topics



Leave a reply



Submit