Use derived type in base abstract class

Well, I have several different classes based on a base class. This base class is abstract, containing commom methods.

One method is the Copy method, which should be present in all derived classes, so I put it in the base class. BUT, I want it to return the derived type not the base and not the object.

The solution I got for this uses a parameter like:

 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 goal here is

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


One workaround.

The best I could do so far is one of the comments below, but it still uses a common 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 } } 
+6
source share
4 answers

You can not. The base class cannot know all future implementations. You will have to use the generic type of the abstract class (like you) or the 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 type checking in a 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 a lot of trust in the implementation of the derived class, as it will blindly cast the return value of the abstract method. The compiler will allow you to return another type that implements CopyableClass in the derived type, but it will be a run-time error. This is not a problem if you have absolute control over all derived implementations (i.e. your abstract class also has an internal constructor).

+4
source

In fact, you want to implement the copy in the base class and return it T This will cause you to call it with a type argument, and it will return that type.

 public static T Copy<T>() where T : CopyableClass { T retVal = new T(); // do whatever copying is required return retVal; } 

To call you do:

 DerivedClass d = Copy<DerivedClass>(); 

Your code to actually make a copy may be a little more work to do a generic one, but it's worth the effort since you will have a single Copy() implementation that works for any derived type. I don’t know which logic belongs to the method, so I just clarified the situation. In addition, I would recommend checking the generalizations as a whole. They are often the best option for such things. If your implementations must be unique to the base class, keep the same method definition, but make it abstract, and then override it in the base classes.

0
source

This will allow you to apply this base class to the derived type and return it.

 public abstract class BaseClass<TDerived> : where TDerived: BaseClass<TDerived> { public TDerived DoSomethingCommon(string param) { var derivedType = (TElement)this; //do something. return derivedType; } } 
0
source

This solution includes the middle class, but I think it is more related to what you are looking for. At least you get the potential 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> { } 
0
source

Source: https://habr.com/ru/post/948571/


All Articles