简体   繁体   中英

Is it possible to call a derived class constructor from a base class constructor?

I have an abstract base class from which I derive two classes. The abstract class has a protected field which is initialized by constructors in the derived classes. Each of the derived classes has two constructors, the first constructor of each class initializes the field and the second constructor modifies the initialization of the first by calling the first constructor. The second constructor of both derived classes are exactly the same but the first constructor is different between the two derived classes. Is there some way to put the second constructor in the base class?

Here is an example to illustrate what I'm trying to say:

public abstract class A {
    protected int[] field1;

    public void someMethod() {
        //somethingsomething
    }
}

public class B : A {
    public B() {
        //body X
        //this initializes field1 in some way
    }

    public B(bool p) : this() {
        //body Y
        //this initializes field1 in some way + modification
    }
}

public class C : A {
    public C() {
        //body Z
        //this initializes field1 in another way
    }

    public C(bool p) : this() {
        //body Y
        //this initializes field1 in another way + modification
    }
}

What I would like to do, is to find some way so as to not have to repeat body Y twice. I was thinking of putting body Y of B(bool p) and C(bool p) in a constructor in class A as A(bool p) , then have B(bool p) and C(bool p) call the base class constructor with : base(bool p) followed by an empty body, but then realized the base class constructor would have to call the derived class constructor.

This sounds stupid to me too. Although I am not sure, it's because I have this feeling that calling something from a derived class from a base class is something that can only be done at run time and there really is no way to check this at compile time. I'm just trying to find a way to follow the DRY principle.

Thanks.

Short answer: no. That would be breaking the object-oriented paradigm, so you wouldn't want to be able to do that anyway. Think about it this way: an abstract base class can be extended by an arbitrary number of classes, but if it was tightly coupled to one of the child classes, how would that impact the other ones?

public class BaseClass {
     // Call child class constructor
     public BaseClass() : A() { }
 }

 public class A : BaseClass {
      public A() { ... }
 }

 // How should BaseClass handle this? There is no constructor named "A."
 public class B : BaseClass {
        public B() { ... }
 }

If you want the base class and derived class to share some functionality, you should make it a protected method in the base class. That way, you can call that method from the constructor.

You could also make a constructor on the base class that provides the common functionality and call it from the child class with : base(...) .

The only way a base class can trigger a derived behavior is through polymorphism (having a virtual method in B, and overriding it).

But there's some other way that might be much more inuitive in your case. For example:

public class C : A {
    public C() {
        //body Z
        //this initializes field1 in another way
    }

    public C(bool p) : base(p) {
        //this initializes field1 in another way + modification
    }
}

Please note that in your example, B's default constructor calls A's default constructor, as well as C's default one calls B's default one.

Lastly, you can also consider having a second constructor in A that receives field1 initial value as a parameter, but it depends if your instructions are order-dependent.

If you precise what your constructors do exactly, I might have a more decisive answer for you.

Sincerely,

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM