强制派生类来实现基类的构造函数参数(S) [英] Force derived class to implement base class constructor with parameter(s)

查看:160
本文介绍了强制派生类来实现基类的构造函数参数(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,则用,不提供一个构造函数派生类继承:

  1. 在富不继承默认的构造函数,因为它提供明确的构造函数。
  2. FooBar的确实继承了FooBase()。

然而,同样是不正确的与非默认构造函数FooBase(INT)!

  1. 在富必须明确落实FooBase(int)和调用基(INT)。
  2. 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:

  1. Foo does not inherit the default constructor because it supplies an explicit constructor.
  2. FooBar DOES inherit FooBase().

HOWEVER, the same is not true with the non-default constructor FooBase(int)!

  1. Foo MUST explicitly implement FooBase(int) and call base(int).
  2. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆