Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use derived type in base abstract class

Ok, I have a number of different classes deriving from a base class. This base class is an abstract containing commom methods.

One of the methods is a Copy method, wich should be present in all derived classes, so, I've put it in the base class. BUT, I want it to return the derived type not the base nor object.

The solution I got for that, is using a type paramter:

abstract class CopyableClass<T>
{
    public abstract T Copy();
}

class DerivedClass : CopyableClass<DerivedClass>
{
    public override DerivedClass Copy()
    {
        //do what is needed for copy and return a new DerivedClass
    }
}

So, the main purpose here is to

Remove the type parameter in the base class and still make the method return the corresponding derived type.


One workaround.

The best thing I could do so far is one of the comments below, but it still uses a generic parameter

abstract class BaseClass
{
    //base methods not related to deriving type
}

interface ICopyable<T>
{
     T Copy();
}

class DerivedClass : BaseClass, ICopyable<DerivedClass>
{
    public DerivedClass Copy()
    {
        //do what is needed for copy and return a new DerivedClass
    }
}
like image 370
Daniel Möller Avatar asked Jul 02 '13 17:07

Daniel Möller


People also ask

Can you derive from an abstract class?

Note that you can derive an abstract class from a nonabstract class, and you can override a non-pure virtual function with a pure virtual function. You can call member functions from a constructor or destructor of an abstract class.

Can we assign derived instance to base class?

In C++, a derived class object can be assigned to a base class object, but the other way is not possible.

Can base class access derived class properties?

No, you cannot access any derived class members using base class pointer even pointing to a derived class instance. However you can access those values though methods of derived class. Make sure you declare the methods as virtual in your base class.

Is derived class a subset of base class?

The derived class inherits all members and member functions of a base class. The derived class can have more functionality with respect to the Base class and can easily access the Base class. A Derived class is also called a child class or subclass.


2 Answers

You can't really. The base class can't possibly know all the future implementations. You'll have to resort to a generic abstract class (like you did) type or a generic Copy method.

public abstract class CopyableClass
{
    public abstract T Copy<T>() where T : CopyableClass;
}

public class DerivedClass : CopyableClass
{
    public override T Copy<T>()
    {
        if(typeof(T) != typeof(DerivedClass))
            throw new ArgumentException();

        // return your copy
    }
}

Or, if you want to generalize the type check in your base class:

public abstract class CopyableClass
{
    public T Copy<T>() where T : CopyableClass
    {
        if(GetType() != typeof(T))
            throw new ArgumentException();

        return (T) Copy();
    }

    protected abstract CopyableClass Copy();
}

public class DerivedClass : CopyableClass
{
    protected override CopyableClass Copy()
    {
        return // Your copy;
    }
}

Note that the second method puts alot of trust into the implementation of the derived class as it'll blindly cast the return value of the abstracted method. The compiler will let you return another type, implementing CopyableClass, in a derived type but it will be a runtime error. This is not a problem if you have the absolute control over all of the derived implementations (ie your abstract class also have an internal constructor).

like image 73
Simon Belanger Avatar answered Oct 04 '22 20:10

Simon Belanger


This solution involves a middle class but I think its more inline with what the you are looking for. At least you get the possible benefit of isolating your copy code

    public abstract class BaseClass
    {
    }

    public abstract class CopyableClass<T> : BaseClass
        where T: BaseClass, new()
    {
        public T Copy()
        {
            var copy = new T(); // Creating a new instance as proof of concept

            return copy;
        }
    }

    public class DerivedClass : CopyableClass<DerivedClass>
    {
    }
like image 32
K Ekegren Avatar answered Oct 04 '22 22:10

K Ekegren