Create an instance of the derived class from the base class

I have my abstract base class A :

public abstract class A : ICloneable { public int Min { get; protected set; } public int Max { get; protected set; } public A(int low, int high) { this.Min = low; this.Max = high; } //... public object Clone() { return new this(this.Min, this.Max); //<-- ?? } } 

which extends my class B :

 public class B : A { public B(int low, int high) : base(low, high) { } //... } 

Since A is abstract, it cannot be created, but a derived class can. Is it possible to create a new instance of class B from class A ?

Suppose class A has many derived classes, how does it know which one needs to be created?

Well, I want to create an instance of the same class (or type) that A is currently.

That is, if I call the Clone method from class B , I want to instantiate a new B. If I call the Clone method from class C , I want to create a new C.

My approach was to write something like:

 return new this(this.Min, this.Max); 

But this does not work and does not compile.

Is it possible to accomplish this in C # ?

If it is not, is there an explanation so that I can understand?

+3
source share
3 answers

While I like Jamiec's solution, I am missing a dirty solution using reflection :)

 public class A { public object Clone() { var type = GetType().GetConstructor(new[] { typeof(int), typeof(int) }); return type.Invoke(new object[] { this.Min, this.Max }); } } 
+4
source

Yes, it is possible with the abstract factory method in your base class

 public abstract class A { public int Min { get; protected set; } public int Max { get; protected set; } public A(int low, int high) { this.Min = low; this.Max = high; } protected abstract A CreateInstance(int low, int high); public object Clone() { return this.CreateInstance(this.Min,this.Max); } } public class B:A { public B(int low, int high) : base(low,high) { } protected override A CreateInstance(int low, int high) { return new B(low,high); } } 
+5
source

This can be done, and your current approach is a well-defined design pattern, although most implementations make Clone abstract virtual method and override it in all subclasses.

 public abstract class A { public abstract A Clone( ); } public class B : A { public override A Clone( ) { return new B( ); } } public class C : A { public override A Clone( ) { return new C( ); } } 

Since you are using C #, you can use the Activator class. You can make the Clone method virtual (not === abstract) with a default implementation.

 public abstract class A { public virtual A Clone( ) { // assuming your derived class contain a default constructor. return (A)Activator.CreateInstance(this.GetType( )); } } 

Edit - If you do not have a constructor without default parameters in all of your derived classes, you can add parameters to the Activator.CreateInstance method

 (A)Activator.CreateInstance(this.GetType( ), this.Min, this.Max); 

For different constructors on derived types, I would recommend that you override the Clone method specifically for these types instead of using the standard Clone implementation.

+1
source

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


All Articles