【问题标题】:Interface with get property, abstract class with get, subclass with get and set带有 get 属性的接口,带有 get 的抽象类,带有 get 和 set 的子类
【发布时间】:2015-09-03 20:33:40
【问题描述】:

我正在尝试有一个接口,它声明一个属性必须有一个 get:

public interface IValue {
    public int Value { get; }
}

然后有一个抽象类也定义它,但保持抽象:

public abstract class BaseClass : IValue {
    public abstract int Value { get; }
}

然后我想让一个子类定义getter并添加一个setter:

public class SubClass : BaseClass {
    public int Value { get; set; }
}

我收到如下错误:

'SubClass.Value' hides inherited member `BaseClass.Value'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword

如果我尝试:

public class SubClass : BaseClass {
    public override int Value { get; set; }
}

我明白了:

`SubClass.Value.set': cannot override because `BaseClass.Value' does not have an overridable set accessor

有什么方法可以让子类在继承自只定义 getter 的抽象类时可选地添加 setter?

更新:澄清一下,我知道我可以做的变通方法。我的目标是看看我能做到这一点的最干净的方法是什么。我不只是在 BaseClass 上抛出公共设置器的原因是因为 BaseClass 的某些子类可能没有公共设置器。最终目标基本上只是为它们常用的时间提供一个通用的 Value getter。

【问题讨论】:

  • 接口的用途是什么?基类和继承都没有实现它。
  • IValue 在这里做什么? :D
  • 只是为了让你的代码编译,你可以这样做public class SubClass : BaseClass { public override int Value { get; private set; } }。注意setprivate
  • @Sinatr 抱歉,BaseClass 实现了 IValue。
  • @deksii 问题是我想让 SubClass 使用公共设置器(尽管另一个 SubClass2 可能没有公共设置器),这就是为什么我不只是给 BaseClass 一个公共设置器。

标签: c# inheritance


【解决方案1】:

您不能覆盖 getter 并添加新的 setter。 当属性被编译成 get_Valueset_Value 方法时,这就是你的代码:

public interface IValue
{
    int get_Value();
}

public abstract class BaseClass : IValue
{
    public abstract int get_Value();
}

public class SubClass : BaseClass
{
    public override int get_Value() { /* ... */ }

    // there's no set_Value method to override in base class
    public override void set_Value(int value) { /* ... */ }
}

至少有三种方式:

  • SubClass 中定义new int Value 属性(注意,还有difference);
  • 覆盖Value属性并在SubClass中添加SetValue方法;
  • BaseClass 中定义setter 并覆盖属性。

【讨论】:

  • 谢谢丹尼斯。我知道发生了什么,但我希望这是一些允许我只覆盖两者之一的语法(因为它们实际上只是两个函数)。对于这个特定的实现,新值的差异是不可接受的,所以我最终选择了第二个。如果您要为选项 2 添加一个快速代码示例(您甚至可以在下面复制/粘贴我的),我会接受这个作为答案。谢谢。
【解决方案2】:
  1. 'SubClass.Value'隐藏了继承的成员'BaseClass.Value'。要使当前成员覆盖该实现,请添加 override 关键字。否则添加new 关键字

是警告而不是错误。它只是说您在抽象类和具体类中都有public int Value。您的抽象类具有此属性的实现,因此当您在具体类中再次声明它时,只需将其替换为新属性。因此,编译器建议您为此目的使用“new”字样。

  1. 要使用public override int Value { get; set; },您必须在基类中将其标记为“virtual”。只有虚拟成员可以被覆盖。

    A 类 { public virtual int Value { get;放; } } B 类:A { public override int Value { get;放; } }

附:默认情况下,接口成员是公共的和抽象的。因此,如果您在接口中声明 getter 和 setter - 您必须在具体类中实现它。

尝试使用此代码:

public interface IValue
{
    int Value { get; set; }
}

public abstract class BaseClass
{
    int value;
    int Value { get { return value; } }
}

public class SubClass : BaseClass, IValue
{
    public int Value { get { return Value; } set { this.Value = value; } }
}

【讨论】:

  • 抱歉,忘记了。我在上面更新了它。 BaseClass 应该实现 IValue。
  • 这不太行,因为我不希望 IValue 说有一个 setter,因为 BaseClass 的一些子类或 IValue 的一些实现类不会有 setter,只有 getter。
  • 有时候,使用私有的setter确实不错。唯一的问题是在这种特殊情况下,我需要为某些子类设置一个公共设置器。
【解决方案3】:

似乎根本没有办法在不预先声明设置器的情况下在中间添加带有抽象类的集合。我尝试了很多不同的组合,但都没有运气。

最后,我这样做了,这并不理想,但至少让我不会到处都有二传手。

public interface IValue {
    public int Value { get; }
}

public abstract class BaseClass : IValue {
    public abstract int Value { get; }
}

public class SubClass : BaseClass {
    protected int val;
    public int Value { get { return val; } }
    public int SetValue (int value) { val = value; }
}

public class SubClassWithoutSetter : BaseClass {
    public int Value { get { return 50; } }
}

基本上,只需做一个“经典”设置器,因为似乎没有一种语法支持让我在事后添加一个设置器属性。

如果 C# 能实现类似的东西就好了:

public int Value { override get; set; } // note: this does not work

【讨论】:

    猜你喜欢
    • 2016-08-07
    • 1970-01-01
    • 2019-09-15
    • 2017-12-16
    • 1970-01-01
    • 1970-01-01
    • 2019-02-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多