是否可以对需要实现构造函数(带参数)的派生类强制执行编译时合同?
我有一个基类与构造函数需要一个参数:
public class FooBase
{
protected int value;
public FooBase(int value) { this.value = value; }
public virtual void DoSomething() { throw new NotImplementedException(); }
}
Run Code Online (Sandbox Code Playgroud)
我想强制我的基类的派生实现相同的构造函数:
public class Foo : FooBase
{
public Foo(int value) : base(value) { }
public override void DoSomething() { Console.WriteLine("Foo: {0}", value); }
}
Run Code Online (Sandbox Code Playgroud)
如果没有实现构造函数,派生类会导致编译器错误,因为基类中没有默认构造函数:
// ERROR: 'Does not contain a constructor that takes 0 arguments'
// Adding default constructor in FooBase eliminates this compiler error, but
// provides a means to instantiate the class without initializing the int value.
public class FooBar : FooBase
{
public override void DoSomething() { Console.WriteLine("FooBar: {0}", value); }
}
Run Code Online (Sandbox Code Playgroud)
在派生类中添加默认构造函数FooBar()会使编译器错误无效,但是提供了一种实例化FooBar的危险方法,而不需要初始化所需的基类int值.因为我正在使用工厂(见下文),所以静默编译器错误只会导致稍后的运行时错误.我想强制FooBar实现FooBar(int)
有趣的观察:
如果将默认构造函数FooBase()添加到FooBase,那么它将由不提供构造函数的派生类"继承":
但是,非默认构造函数FooBase(int)也是如此!
我不想在基类中使用默认构造函数,因为实例是使用提供所需"设置"参数的工厂方法创建的.此处未说明该工厂方法(使用Activator.CreateInstance()方法).
以下是派生类应该实例化的方式:
static void Main(string[] args)
{
FooBase myFoo = new Foo(4); // Works, since Foo(int) is implemented.
// ERROR: 'Does not contain a constructor that takes 1 arguments'
FooBase myFooBar = new FooBar(9); // Fails to compile.
}
Run Code Online (Sandbox Code Playgroud)
因为我使用的是工厂 - 而不是如图所示的直接实例化 - 所以没有编译器错误.相反,我得到一个运行时异常:'找不到类型的构造函数.'
不可行的解决方案:
似乎提供基类不能强制构造函数的合同.
解决方法:
如果将默认构造函数FooBase()添加到FooBase,那么它将由不提供构造函数的派生类"继承":
这是不正确的 - 一般来说构造函数永远不会被继承.为不提供任何其他构造函数实现的类自动提供默认构造函数.
您可以在为您提供Init()方法的接口上设置约束:
public interface IInit
{
void Init(int someValue);
}
public class FooBase : IInit
{
..
}
Run Code Online (Sandbox Code Playgroud)
你试过了吗
public class FooBase
{
protected int value;
private FooBase(){}
public FooBase(int value) { this.value = value; }
public virtual void DoSomething() { throw new NotImplementedException(); }
}
Run Code Online (Sandbox Code Playgroud)
私有构造函数阻止无参数构造函数的选项