在覆盖中将属性添加到属性

时间:2011-05-19 12:05:30

标签: c# properties abstract

为什么在实现接口时允许更改属性中getter或setter的可见性和存在?

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; }
}

......在实现抽象类时执行相同的操作并不合法吗?

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; }
}

4 个答案:

答案 0 :(得分:12)

接口声明了类必须具有的公共属性(它只是一个契约)。这意味着你需要拥有这些属性,但可以添加它们。

抽象类声明了这些属性的实际结构。因此,如果您没有抽象基础中的setter,则无法在实现中添加它 当你编写覆盖修饰符时,它会在基类中查找要覆盖的内容。

答案 1 :(得分:7)

如果你认为吸气剂和制定者最终会变成它们的方法,那么它可能会变得更加清晰。

对于界面,您要定义:

interface IFoo
{
    string GetBar();
}

可以将其视为“实现此接口的所有类必须包含此方法。” 你的两个课都这样做:

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

他们也实现了SetBar(),但这并不重要;他们已经完成了界面定义的合同并且是有效的。

另一方面,抽象类是这样的:

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

这意味着所有子类都必须为GetBar()

提供方法体

你上课的是:

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

通过将override修饰符放在SetBar方法的前面,编译器期望在基类中找到抽象或虚拟版本。你没有,所以编译失败。

答案 2 :(得分:0)

抽象类是一个无法实例化但必须继承的类。抽象类可以完全实现,但通常部分实现或根本不实现,从而封装了继承类的通用功能。

相比之下,界面是一组完全抽象的成员,可以被认为是定义行为契约。接口的实现完全留给开发人员。

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

答案 3 :(得分:0)

根据C#规范

  

用于实现的访问者   界面可能没有   访问修饰符。如果只有一个   accessor用于实现   接口,其他访问者可能是   使用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
  }
}

这意味着可以在实现接口的类上修改访问权限。但是,抽象类声明了一个实现,您无法使用派生类更改它。