kni*_*ttl 5 c# language-agnostic
与继承者实现一个抽象的getter-only属性相比,拥有readonly字段有什么优点和缺点(在这里使用C#作为例子,但我想这并不重要).
以下是两种方法:
只读字段; 继承者必须在构造函数中注入值
interface IFace {
  public int Field { get; }
}
abstract class Base : IFace {
  private readonly int field;
  protected Base(int field) {
    this.field = field;
  }
  public int Field { get { return this.field; } }
}
class Impl {
  public Impl() : base(1) {
  }
}
抽象的getter-only属性; 继承者必须实现该属性
interface IFace {
  public int Field { get; }
}
abstract class Base : IFace {
  // default constructor can be used
  public abstract int Field { get; }
}
class Impl {
  public override int Field { get { return 1; } }
}
这两个实现都公开了一个int Field不会改变的公共getter-only属性.
但是,我可以看到以下差异:
值field绑定到每个实例,没有什么能阻止继承者允许在其构造函数本身中接收值(public Impl(int field) : base(field)).
绑定到实例时,每个单个实例都需要该字段的内存.这可能不是什么大问题,但绝对值得记住.
传达的意图是:该值只能在构造函数中设置,并且以后不能更改(不考虑反射).
(返回)值Field绑定到每种类型,但是没有什么能阻止继承者在每次调用getter时生成/计算值,每次都可能返回不同的值.public overried int Field { get { return DateTime.UtcNow.Second; } }
内存只需要"在IL中",因为该值(通常)不会存储在任何地方,但总是在返回之前计算(导致加载指令,仅此而已).
传达的意图应该是:值绑定到类型(并且不应该在调用之间改变,但是没有办法强制它,对吧?).但更确切地说,意图是:您需要提供此属性,我不关心您如何实现它以及它返回的值.
我有什么重要的差异吗?是一个优先于另一个,还是需要根据具体情况决定?
我想我正在寻找一个构造/模式/语言功能,它将只读(常量)值绑定到一个类型,但是在实例级别公开该值.我知道我可以在每个继承类型中使用静态字段,但是没有办法从公共基础(或接口)强制执行此操作.此外,仅具有对此类型实例的引用时,无法调用静态字段.思考?我很高兴收到不同编程语言的答案
您给出的模式 1 和模式 2 之间有一个关键区别。
模式 1 不允许在构造类后返回不同的值,因为基类仅在构造函数中使用字段。
模式 2 允许子类在不同时间返回不同的值。基本上 - 如果子类决定覆盖,则基类不会强制执行任何操作。
因此,这实际上取决于您想要实现的目标和您的领域逻辑。
关于您试图实现的意图 - 在我看来 - 解决实现意图的方法之一是声明一个虚拟方法(类似于基类中的 getReadOnlyField() )而不是只读属性。然后 - 子类可以自由地重写虚拟方法 - 如果它们不重写 - 基本实现仍然会被强制执行。
这个问题不可能有任何一个正确答案。将有多种方法来解决这个问题。这一切都取决于您的要求。