1

I am having a C# abstract class which have some methods to be implemented by its children.

Though it is so, the initialization values for those children consist of two parts: one which is the same as the parent, and another one which is unique to the children.

public abstract class parentClass {
    public abstract bool IsInputValid(string input); //children must implement this
    public parentClass () {
       //Some shared initialization
    }
}

If the class is not abstract we could do something like this to implement that

public class parentClass {
    public parentClass (string input) {
       //Some shared initialization
    }
}

public class childClass : parentClass {
    public childClass (string input) : base (input) {
       //Some unique initialization
    }
}

But that cannot be done using abstract class and some more, the method not need not to be implemented (since it is not abstract).

So I am in a dilemma here. On one hand, I want to have some base initialization called and on the other, I also want to have some methods enforced.

So my question is, how do we normally implement such case? On one hand it is enforcing some base initialization, and on another some methods.

Note: I am new to abstract class so I would be glad to receive any inputs regarding it.

Where do I declare wrongly (if any)? If we cannot do so, is there a way to get around to produce the same result (that is, to enforce the child class to use certain signature for constructor)?

Ian
  • 30,182
  • 19
  • 69
  • 107
  • Why do you need to do that? – Yacoub Massad Jan 06 '16 at 12:01
  • 1
    Please read [ask] and try searching first. The top 10 web search results for "C# force constructor implementation" are Stack Overflow hits for me. Also, as long as your base class contains a constructor, derived classes must implement a constructor anyway, or they won't compile. – CodeCaster Jan 06 '16 at 12:02
  • @CodeCaster I am quite new to the abstract class, Sir. I did search, but I cannot really tell if the dupe is actually asking the same question till you told me. My apologies.. And thank you for the re-direction.. – Ian Jan 06 '16 at 12:08
  • The abstract part isn't really relevant. There's no such thing as constructor inheritance, abstract or not, and abstract constructors are not possible in C#. Happy to help. – CodeCaster Jan 06 '16 at 12:10

4 Answers4

1

You cannot enforce the signature or even existence of constructors of your derived classes. (or any class for that matter)

I'm afraid that's the end of the story. You aren't doing anything wrong, it's just not possible.

nvoigt
  • 75,013
  • 26
  • 93
  • 142
  • How do we normally work around with it, Sir? I am quite new in using abstract class (this is the first time actually). – Ian Jan 06 '16 at 12:04
  • You should tell us why you think you need it, you can only construct instances of actual concrete types, ie. `new DerivedClass(...)`, why do you feel the need to enforce the presence of a particular constructor for that class? – Lasse V. Karlsen Jan 06 '16 at 12:23
1

Since you can't override constructors in c#, you cannot enforce the existence of a certain constructor in the derived class .

This means:

  • a constructor cannot be abstract, virtual etc
  • constructors aren't polymorphically
Community
  • 1
  • 1
jHilscher
  • 1,810
  • 2
  • 25
  • 29
1

There should be no need to enforce this. You say that the base class has some common initialization and the child classes have their own specialized initialization as well.

This is enforced already, if you have this:

public abstract class Base
{
    protected Base(int value) { ... }
}

Then you have a couple of guarantees:

  • Nobody can construct an object of the type Base since it is abstract
  • Nobody can construct an object that inherits from Base without indirectly calling the only existing constructor of Base, that takes an int value parameter.

The last part there is important.

A child class can deal with this type of base constructor in at least three ways:

  • It can provide a constructor that looks identical save the name of it, just passing the value down to the base constructor:

    public class Child : Base
    {
        public Child(int value) : base(value) { ... }
    }
    
  • It can provide a constructor that has this parameter but has additional parameters to the child class constructor as well:

    public class Child : Base
    {
        public Child(int value, string other) : base(value) { ... }
    }
    
  • It can provide a constructor that doesn't have the parameter to the base class, but manages to compute this parameter:

    public class Child : Base
    {
        public Child(string other) : base(other.Length) { ... }
    }
    

The last part also handles the case where the child constructor has no parameters at all:

public class Child : Base
{
    public Child() : base(new Random().Next(100)) { ... }
}

Regardless of which approach you use, it is impossible to call the base class constructor without passing a value for that parameter, hence you have enforce the following:

  • Child classes has to be aware of the base class constructor and its parameter

But you cannot, and should not, try to enforce the presence of a particular constructor with a specific signature.


Now, having said that, what if you want to create some sort of common way to construct two distinct child classes, that has such different constructors, in such a way that code that uses them doesn't need to know the specifics of either constructor?

Enter the factory pattern (Wikipedia):

In class-based programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method—either specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes—rather than by calling a constructor.

(quoted text copied from entry paragraph in the Wikipedia-article)

Here's a way to abstract away the presence and knowledge of such different constructors and child classes:

void Main()
{
    Test(new Child1Factory());
    Test(new Child2Factory());
}

public void Test(IBaseFactory baseFactory)
{
    Console.WriteLine("In Test(...");
    var b = baseFactory.Create();
}

public class Base
{
    public Base(int value)
    {
        Console.WriteLine($"Base.ctor({value})");
    }
}

public interface IBaseFactory
{
    Base Create();
}

public class Child1 : Base
{
    public Child1(int value) : base(value)
    {
        Console.WriteLine($"Child1.ctor({value})");
    }
}

public class Child1Factory : IBaseFactory
{
    public Base Create() => new Child1(42);
}

public class Child2 : Base
{
    public Child2(string name) : base(name.Length)
    {
        Console.WriteLine($"Child2.ctor({name})");
    }
}

public class Child2Factory : IBaseFactory
{
    public Base Create() => new Child2("Meaning of life");
}

Pay special attention to the Test(...) method, as this has no knowledge of which Base child it will get, nor how to construct such an object. If you later on add new child types from Base, you will have to provide new factories as well but existing code that uses these factories should not need to be changed.

If you want a simpler factory pattern all you have to do is replace the interface and factory classes with a delegate:

void Main()
{
    Test(() => new Child1(42));
    Test(() => new Child2("Meaning of life"));
}

public void Test(Func<Base> baseFactory)
{
    Console.WriteLine("In Test(...");
    var b = baseFactory();
}

Final note here. Since the factory pattern means you will have to create a different type that does the actual construction of the object you can enforce the signature of that other type, either by

  • Adding parameters to the Create method on the factory interface
  • Specifying a delegate that has parameters to the factory delegate

This means you can enforce the signature of "the creation process". Still, you cannot enforce the presence or signature of a particular constructor, but the constructor is just a means to an end, create an object, and with the factory pattern you can actually formalize this pattern in your code and thus you should get what you want.

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
  • Thanks for your clarification on this issue. I almost thought to make a base class which have some base initialization value and an interface class which has the methods signatures and derive the child class from both the base class and the interface class. Now I know that the base constructor of the abstract class will always be called (do I understand this correctly?) – Ian Jan 06 '16 at 12:59
  • That is correct. If you have multiple protected or public constructors in the base class then when writing the child types you can chose which base constructor to call in each particular child constructor *but you have to call one*. If you have a parameterless constructor in the base - `public Base() { ... }`, then you can ommit the `: base()` call in the child constructors but the base constructor will still be called. You will always call a base constructor. The only way to get a new object without going through any constructors are the more obscure ways to deserialize, let's not go there. – Lasse V. Karlsen Jan 06 '16 at 13:02
  • Thank you, Sir. Really appreciate your effort to clarify to new comer in details. I hope your reputation keeps going up. (voted up and accepted) – Ian Jan 06 '16 at 13:06
0

You cannot have an abstract constructor, but neither is there any need to. All you need to do is remove the "abstract" keyword from your parentClass and you should be good to go.

Shazi
  • 1,490
  • 1
  • 10
  • 22