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:
HOWEVER, the same is not true with the non-default constructor FooBase(int)!
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:
It appears that supplying a base class cannot enforce a contract on constructors.
Work-around:
To pass arguments to a constructor in a base class, use an expanded form of the derived class' constructor declaration, which passes arguments along to one or more base class constructors. Here, base1 through baseN are the names of the base classes inherited by the derived class.
How to call the parameterized constructor of base class in derived class constructor? To call the parameterized constructor of base class when derived class's parameterized constructor is called, you have to explicitly specify the base class's parameterized constructor in derived class as shown in below program: C++
In C++, a derived-class constructor always invokes a constructor for the base class. If an explicit invocation does not appear in the member-initializer list, there is an implicit call to the default constructor.
In inheritance, the derived class inherits all the members(fields, methods) of the base class, but derived class cannot inherit the constructor of the base class because constructors are not the members of the class.
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 { .. }
Did you try
public class FooBase { protected int value; private FooBase(){} public FooBase(int value) { this.value = value; } public virtual void DoSomething() { throw new NotImplementedException(); } }
the private constructor prevents the option of parameter-less constructor
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With