Adding setters to properties in overrides

狂风中的少年 提交于 2020-01-02 00:32:08

问题


Why is it allowed to change the visibility and existence of getters or setters in a property when implementing an interface?

interface IFoo
{
    string Bar { get; }
}

class RealFoo : IFoo
{
    public RealFoo(string bar)
    {
        this.Bar = bar;
    }

    public string Bar { get; private set; }
}

class StubFoo : IFoo
{
    public string Bar { get; set; }
}

...and not legal to do the same when implementing an abstract class?

abstract class AbstractFoo : IFoo
{
    public abstract string Bar { get; }
}

class RealFoo : AbstractFoo
{
    public RealFoo(string bar)
    {
        this.Bar = bar;
    }

    // Cannot override because 'Bar' does not have an overridable set accessor
    public override string Bar { get; private set; }
}

回答1:


The interface declares what public properties the class must have (It's just a contract). Which means you need to have those properties, but can add to them.

The abstract class declares the actual structure of those properties. So if you don't have the setter in the abstract base, you can't add to it in the implementation.
When you write the override modifier it looks in the base class for something to override.




回答2:


It perhaps becomes clearer if you think of the getters and setters as the methods that they eventually become.

In the case of the interface you are defining this:

interface IFoo
{
    string GetBar();
}

Which can be read as "all classes that implement this interface must include this method." Both of your classes do:

class RealFoo : IFoo
{
    public string GetBar();
    private void SetBar(string value);
}

they also implement SetBar(), but that is immaterial; they have fulfilled the contract defined by the interface and are valid.

The abstract class, on the other hand is this:

abstract class AbstractFoo : IFoo
{
    public abstract string GetBar();
}

Which means that all child classes must provide a method body for GetBar()

The class you made is this:

class RealFoo : AbstractFoo
{
    public override string GetBar();
    public override void SetBar(string value);
}

By putting the override modifier in front of the SetBar method the compiler is expecting to find an abstract or virtual version in the base class. You don't have that so the compilation fails.




回答3:


An abstract class is a class that cannot be instantiated, but must be inherited from. An abstract class may be fully implemented, but is more usually partially implemented or not implemented at all, thereby encapsulating common functionality for inherited classes.

An interface, by contrast, is a totally abstract set of members that can be thought of as defining a contract for conduct. The implementation of an interface is left completely to the developer.

Taken from the MSDN http://msdn.microsoft.com/en-us/library/scsyfw1d(v=VS.71).aspx




回答4:


According to the C# specification

An accessor that is used to implement an interface may not have an accessor-modifier. If only one accessor is used to implement an interface, the other accessor may be declared with an accessor-modifier:

public interface I
{
  string Prop { get; }
}
public class C: I
{
  public Prop {
  get { return "April"; }     // Must not have a modifier here
        internal set {...}    // Ok, because I.Prop has no set accessor
  }
}

That means it is OK to have an access modified on a class implementing the interface. However, the abstract class declares an implementation and you cannot change that with a derived class.



来源:https://stackoverflow.com/questions/6058352/adding-setters-to-properties-in-overrides

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!