从子类提供抽象类成员变量
从具体子类在抽象类中提供值的“正确”方法是什么?
即,我应该这样做:
abstract class A {
private string m_Value;
protected A(string value) {
m_Value = value;
}
public string Value {
get { return m_Value; }
}
}
class B : A {
B() : this("string value") {}
}
或这个:
abstract class A {
protected A() { }
public abstract string Value { get; }
}
class B : A {
B() {}
public override string Value {
get { return "string value"; }
}
}
或其他什么?
如果 Value
属性仅在抽象类中使用,是否应该做不同的事情?
What is the 'correct' way of providing a value in an abstract class from a concrete subclass?
ie, should I do this:
abstract class A {
private string m_Value;
protected A(string value) {
m_Value = value;
}
public string Value {
get { return m_Value; }
}
}
class B : A {
B() : this("string value") {}
}
or this:
abstract class A {
protected A() { }
public abstract string Value { get; }
}
class B : A {
B() {}
public override string Value {
get { return "string value"; }
}
}
or something else?
And should different things be done if the Value
property is only used in the abstract class?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我通常更喜欢第一种方法,因为它在子类中需要更少的代码。
然而,我承认第二种方法的语义在某种程度上更清晰。覆盖该属性表示“此属性的实现是我的身份的一部分。”传递构造函数参数具有不同的含义:“我正在另一个东西中设置一个值,它恰好是我的基类。”它意味着组合(has-a)而不是继承(is-a)。
在这种情况下,您绝对应该使用第一种(面向构造函数)方法,这样您就可以从子类中隐藏该实现细节。
同样,如果您需要在构造函数中使用该值;正如 Marc 提到这是一个实际的技术使用第一种方法的原因。尽管在这种特定情况下这并不重要,但如果有人稍后修改属性重写以使用派生类中的某些其他成员变量,您可能会遇到一个微妙的错误。
I usually prefer the first approach because it requires less code in child classes.
However, I admit that the semantics of the second approach are clearer in a subtle way. Overriding the property says "this property's implementation is part of my identity." Passing a constructor argument has a different connotation: "I'm setting a value in this other thing, which just happens to be my base class." It implies composition (has-a) rather than inheritance (is-a).
In this case, you should definitely use the first (constructor-oriented) approach so you can hide that implementation detail from subclasses.
Likewise if you need to use the value in the constructor; as Marc mentioned this is an actual technical reason to use the first approach. Though it wouldn't matter in this specific scenario, if someone later modifies the property override to use some other member variable in the derived class, you might have a subtle bug on your hands.
这取决于;基类需要在 ctor 中了解它吗?如果是这样,
override
方法可能是一个坏主意(virtual
在ctor内部不能很好地工作)。否则,两者都可以。It depends; does the base-class need to know about it in the ctor? If so, the
override
approach may be a bad idea (virtual
doesn't work very well inside the ctor). Otherwise, either is OK.我认为第二个习惯用法更好,因为它更易于管理(如果您的基类需要在派生类中定义多个属性,则构造函数可能会变得混乱)。信息的来源也更加清晰。如果您看到
Value
属性,您就知道它是在子类中定义的。在第一个示例中,您必须跟踪 m_Value 变量的定义点,该变量可以在基类中进行修改。I think the second idiom is better, as it is more manageable (if your base class needs multiple properties defined in a derived class, the constructor can get messy). It is also clearer where the information comes. If you see the
Value
property you know that it is defined in a subclass. In the first example, you have to track the definition point of them_Value
variable, which could be modified in the base class.我认为这几乎是一样的,选择一种方式并坚持使用以保持连贯性。
您的两个解决方案都强制派生类提供一个值,这很好;一个可能的替代方案,以防不需要值:
我个人的偏好是您的第一个选择(构造函数参数),因为我个人认为这是更清晰的选择,但这实际上是一个品味问题。
I think it's pretty much the same, choose one way and stick to that for coherence.
Both your solutions are forcing the derived class to provide a value, which is good; a possible alternative, in case a value should not be required:
My personal preference is your first option (constructor parameter), because I personally think that it's the clearer one, but it's really a matter of taste.
这取决于。
如果我需要修改抽象类中的
Value
,我将使用第一种方法。仅当我需要从
A
继承许多类并且在某处需要将继承的类装箱到基本抽象类时,我才会使用第二种方法。如果上述两种情况都不成立,我将使用第二种更易于管理和干净的方法。
如果
Value
仅在抽象类中使用,我会将其声明为private
字段而不是属性。It depends.
I will use the first way if I need to modify
Value
in abstract class.I will use the second way only if I need to inherit many classes from
A
and somewhere, I need to box the inherited classes to the base abstract class.If both of the above are not true, I will use the second approach which is more manageable and clean.
If
Value
is only used in abstract class, I will declare it as aprivate
field instead of a property.第二种情况的一个主要优点是它允许子类定义可能比简单标量值更复杂的 Value 属性的行为。例如,您可能希望根据子类定义的其他字段来计算值。对于第一种方法,这是不可能的,但第二种方法允许这样做。
One major advantage of the second case is that it allows a subclass to define behaviour for the Value property that may be more complex than a simple scalar value. For example, you might want to compute the Value based on other fields that the subclass defines. With the first approach, that is an impossibility, but the second approach allows for that.
我更喜欢第二个。如果该值是常量或可以在运行时计算,它允许您提供一个值,而无需向类添加实际字段。您拥有的状态越少(字段越少),您可能会发现代码越易于维护。
I prefer the second. It lets you provide a value without adding an actual field to the class if the value is constant or can be calculated at runtime. The less state you have (fewer fields) the more maintainable you'll likely find the code to be.