强制派生类来实现基类的构造函数参数(S) [英] Force derived class to implement base class constructor with parameter(s)
问题描述
是否可以强制执行派生类需要实现一个构造函数(带参数)?
编译时合同我有一个构造函数需要一个参数的基类:
公共类FooBase
{
保护int值;
公共FooBase(int值){THIS.VALUE =价值; }
公共虚拟无效的doSomething(){抛出新的NotImplementedException(); }
}
我想逼我的基类的派生来实现同样的构造器:
公共类Foo:FooBase
{
公共美孚(int值):基地(价值){}
公众覆盖无效的doSomething(){Console.WriteLine(富:{0},值); }
}
如果没有构造函数来实现,派生类会导致编译器错误,因为在基类没有默认构造函数:
//错误:'不包含一个构造函数0的论点
//在FooBase添加默认的构造消除了这种编译器错误,但
//提供了实例化类没有初始化的int值的方法。
公共类FooBar的:FooBase
{
公众覆盖无效的doSomething(){Console.WriteLine(FooBar的:{0},值); }
}
添加一个默认的构造函数,FooBar的(),在派生类中沉默的编译器错误,但提供了实例FooBar的不被初始化所需的基类int值的危险方法。因为我使用的是工厂(见下文),沉默的编译器错误只是导致运行时错误后。我想迫使FooBar的实施FooBar的(INT)
有趣的现象:
如果默认构造函数,FooBase(),加入到FooBase,则用,不提供一个构造函数派生类继承:
- 在富不继承默认的构造函数,因为它提供明确的构造函数。
- FooBar的确实继承了FooBase()。
然而,同样是不正确的与非默认构造函数FooBase(INT)!
- 在富必须明确落实FooBase(int)和调用基(INT)。
- FooBar的没有继承非默认的构造函数相同的方式,一个默认的构造函数是继承!
我不希望在基类中默认的构造函数,因为实例使用提供了一个需要设置参数工厂方法创建的。该工厂方法这里没有示出(使用Activator.CreateInstance()方法)。
下面是派生类的方式应该被实例化:
静态无效的主要(字串[] args)
{
FooBase myFoo =新的Foo(4); //工程,因为美孚(INT)被实现。
//错误:'不包含一个构造函数1个参数
FooBase myFooBar =新FooBar的(9); //编译失败。
}
由于我使用的是厂家 - 不直接实例如图所示 - 没有编译器错误。相反,我得到一个运行时异常:构造上没有的类型
失灵了解决方案:
- 在接口不支持构造函数。
- 在构造函数不能是虚拟的或抽象的。
看来,提供一个基类不能强制执行构造合同。
解决方法:
- 与物业通过设置参数提供基类的默认构造函数。
如果一个默认的构造函数,FooBase() 加到FooBase,那么它是 继承由派生类做 不能提供一个构造器:
这是不正确 - 一般的构造函数永远继承。默认构造函数自动提供,不提供任何其他的构造函数实现的类。
您可以把一个约束,提供了一个init()方法用于在接口上:
公共接口IInit
{
无效初始化(INT someValue中);
}
公共类FooBase:IInit
{
..
}
Is it possible to enforce a compile-time contract on derived classes requiring implementation of a constructor (with parameter)?
I have a base class with a constructor requiring a parameter:
public class FooBase
{
protected int value;
public FooBase(int value) { this.value = value; }
public virtual void DoSomething() { throw new NotImplementedException(); }
}
I'd like to force derivations of my base class to implement the same constructor:
public class Foo : FooBase
{
public Foo(int value) : base(value) { }
public override void DoSomething() { Console.WriteLine("Foo: {0}", value); }
}
If no constructor is implemented, derived classes causes a compiler error because there is no default constructor in the base class:
// 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); }
}
Adding a default constructor, FooBar(), in the derived class silences the compiler error, but provides a dangerous means of instantiating FooBar without the required base class int value being initialized. Because I'm using a factory (see below), silencing the compiler error only results in a run-time error later. I'd like to force FooBar to implement FooBar(int)
INTERESTING OBSERVATION:
If a default constructor, FooBase(), is added to FooBase, then it is 'inherited' by derived classes that do not provide a constructor:
- Foo does not inherit the default constructor because it supplies an explicit constructor.
- FooBar DOES inherit FooBase().
HOWEVER, the same is not true with the non-default constructor FooBase(int)!
- Foo MUST explicitly implement FooBase(int) and call base(int).
- FooBar FAILS to 'inherit' the non-default constructor the same way that a default constructor is inherited!
I do not want a default constructor in the base class because instances are created using a factory method that supplies a needed "settings" parameter. That factory method is not illustrated here (which uses the Activator.CreateInstance() method).
Here is the way derived classes should be instantiated:
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.
}
Because I am using a factory--not direct instantiation as shown--there is no compiler error. Instead, I get a runtime exception: 'Constructor on type not found.'
Unworkable solutions:
- Interfaces do not support constructors.
- Constructors cannot be virtual or abstract.
It appears that supplying a base class cannot enforce a contract on constructors.
Work-around:
- Provide a default constructor in base class along with property to pass settings parameter.
If a default constructor, FooBase(), is added to FooBase, then it is 'inherited' by derived classes that do not provide a constructor:
This is incorrect - constructors in general are never inherited. A default constructor is automatically provided for a class that does not provide any other constructor implementation.
You could put in a constraint on an interface that provides an Init() method for you:
public interface IInit
{
void Init(int someValue);
}
public class FooBase : IInit
{
..
}
这篇关于强制派生类来实现基类的构造函数参数(S)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!