我有一个带有两个构造函数的基类,需要一个参数:
public abstract class StoreBase
{
private readonly SomeObject_sobj;
protected StoreBase(SomeObject sobj)
{
_sobj = sobj;
}
protected StoreBase(OtherObject oobj)
{
_sobj = new SomeObject(oobj);
}
}
然后我有一个派生类:
public class MyDerived: StoreBase
{
}
这会导致编译错误为base class doesn't contain parameterless constructor
。
我的理解是因为MyDerived不包含构造函数,所以编译器添加了一个无参数构造函数(这是众所周知的,与派生类无关)。但是,因为它派生自另一个类,所以基类构造函数需要先运行,并且无法确定应从空的MyDerived构造函数运行哪个构造函数。
基本上我问:如果我真的不需要额外的构造函数逻辑,我可以避免将所有构造函数从Base复制/粘贴到Derived类中吗?我可以说“从基地拿走所有构造函数”而不是全部添加吗?
(是的,我知道我可以/应该将它重构为无参数构造函数和受保护的虚拟Initialize()方法。但我仍然想知道我是否可以使用构造函数并仍然避免复制/粘贴)
答案 0 :(得分:15)
不 - 您还需要在派生类中实现(适当的)构造函数。
派生类只需要使用其中一个基本构造函数 - 因此其中所需的构造函数可能与基类完全不同。它们需要手工实施,即使只是:
public class MyDerived : StoreBase
{
public MyDerived(SomeObject sobj) : base(sobj) {}
public MyDerived(OtherObject oobj) : base(oobj) {}
}
此外:
(是的,我知道我可以/应该将它重构为无参数构造函数和受保护的虚拟Initialize()方法。但我仍然想知道我是否可以使用构造函数并仍然避免复制/粘贴)
虽然我看到这个被吹捧,但我相信这并不总是一个好习惯。在许多情况下,这实际上是有问题的,因为如果它们覆盖受保护的虚拟方法,则依赖于子类来正确调用Initialize。例如,如果子类执行此操作,则可能非常糟糕:
public class MyDerived : StoreBase
{
// .. other stuff
protected override void Initialize()
{
// Leave out, intentionally or accidentally, the following:
// base.Initialize();
}
}
我实际上在大多数情况下都避免这种情况,并在构造函数中初始化(或在私有的非虚拟初始化方法中)。不执行此操作会破坏您的初始化将始终按照您的意图发生的任何保证。
构造函数和构造函数链提供相同的功能,并提供更好的保证。
答案 1 :(得分:3)
不,构造函数不是继承的,并且没有创建基本构造函数副本的快捷方式。
最接近的是实现调用基础构造函数的构造函数。我想你想让它们公开,所以你实际上可以创建一个类的实例:
public MyDerived(SomeObject sobj) : base(sobj) {}
public MyDerived(OtherObject oobj) : base(oobj) {}
答案 2 :(得分:3)
如果您自己没有提供任何构造函数,编译器将只生成默认(无参数)构造函数。一旦定义了构造函数,编译器就不会为你生成一个。
如果您计划序列化类,请记住这一点非常重要,因为序列化需要默认构造函数。如果你给你的类一个非默认的构造函数,那么你还需要提供一个默认的支持序列化,因为再次,一旦你提供任何构造函数,编译器将不会提供一个为你自动。
答案 3 :(得分:2)
不幸的是答案是否定的。
您可以做的一件事是从MyDerived构造函数调用base:
class MyDerived: StoreBase
{
public MyDerived(OtherObject obj) : base (obj) {}
}
答案 4 :(得分:1)
我可以说“从基地拿走所有构造函数”而不是全部添加吗?
没有。 : - (