Search code examples
c#constructorderiving

Base class object as argument for derived class


(Simplified) Scenario:

public class BaseClass
{
    public int BaseClassInt {get; set;}

    public BaseClass(int pBaseClassInt)
    { this.BaseClassInt = pBaseClassInt; }

}

public class DerivedClass : BaseClass
{
    public int DerivedClassInt {get; set;}

    public DerivedClass (int pBaseClassInt, int pDerivedClassInt) : base(pBaseClassInt)
    { this.DerivedClassInt = pDerivedClassInt; }

}

If I want to instantiate a DerivedClass-object I have to pass all arguments required to create a BaseClass-object and a DerivedClass-object. Also for every BaseClass-constructor I have to (at least should in my concrete case) provide a constructor with the same arguments in the derived class, plus arguments for the derived class properties. Then, if I change or delete a constructor in the base class I have to change or delete the corresponding contructor in the derived class(es).

I wonder if it is possible to use a constructor for the derived class which accepts a base class-object as an argument:

public DerivedClass(BaseClass pBaseClassObejct, int pDerivedClassInt)
{
    // to make clear what I intend to do - looks silly of course
    this = (DerivedClass)pBaseClassObject;
    this.DerivedClassInt = pDerivedClassInt;
}

This could be called:

DerivedClass DerivedClassObject = new DerivedClass((new BaseClass(1),2);

If constructors in the base class would change, I wouldn´t have to mind it for the derived class. Is there any way to achieve this?


Solution

  • Think about this line for a moment:

    this = (DerivedClass) pBaseClassObject;
    

    Let's ignore the fact that you cant set this directly that way, and focus on the rest.

    Imagine Giraffe and Elephant are both implementations of AfricanAnimal:

    // By extension, ellie is also an AfricanAnimal    
    Elephant ellie = new Elephant(); 
    
    // assume ellie is passed in as a param here (she can 
    // be, because she is an AfricanAnimal after all!):
    public Giraffe(AfricanAnimal ellie) 
    {
        this = (Giraffe) ellie; // Can't do this!
    }
    

    You can't (and would not want to) force ellie into being a giraffe, because a giraffe may have properties etc. that ellie lacks, and ellie may have properties that Giraffes don't have. Yet, using an AfricanAnimal as your parameter type there, would allow for just that.

    Note: You could write that code and pass a Giraffe in, and all would be fine, but then again, that makes little sense; then you might as well use the Giraffe type as the parameter.

    If you replace this with an instance variable, you would be able to compile with something like the following...

    public Giraffe(AfricanAnimal ellie) 
    {
        this.varOfTypeGiraffe = (Giraffe) ellie; 
    }
    

    ... but as soon as you run it with an Elephant as a a prameter, you will get an exception similar to:

    InvalidCastException: Unable to cast object of type 'Elephant' to type 'Giraffe'.