【问题标题】:Create an instance of derived class from the base class从基类创建派生类的实例
【发布时间】:2014-09-29 13:42:26
【问题描述】:

我有我的抽象基类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); //<-- ??
    }
}

这是由我的班级B扩展的:

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

    //...
}

由于A是抽象的,它不能被实例化,但派生类可以。 是否可以从类 A 中创建类 B 的新实例?

假设类A有很多派生类,它怎么知道要实例化哪一个?

好吧,我想实例化我当前的 A 是相同的类(或类型)。

也就是说,如果我从一个类 B 调用 Clone 方法,我想实例化一个新的 B。 如果我从类 C 调用 Clone 方法,我想实例化一个新的 C。

我的方法是这样写:

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

但这似乎既不工作也不编译。

是否有可能在 C# 中实现这一点?

如果不是,是否有解释让我能理解?

【问题讨论】:

  • 这不能回答你的问题,但你为什么不使用 this.MemberwiseClone() 代替?
  • 我不知道 MemberwiseClone() 方法,但我只是希望副本是一个新实例,具有相同的构造函数参数。 MemberwiseClone 可能做的任何其他处理都是无用的
  • 如果B construtor 再增加一个参数呢?
  • 我希望这不会发生

标签: c# oop inheritance abstract-class instantiation


【解决方案1】:

是的,这可以通过基类上的抽象工厂方法实现

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);     
   }
}

【讨论】:

  • 我也想到了这个解决方案,但我期待不在每个派生类中添加构造代码,而是让 C# 为我做这件事,实例化任何用于扩展 A 的派生类。我希望我能很好地解释自己
  • @MatiCicero - 这是可行的,但您将涉足大量反思。考虑一下这是否适合您
  • 我将测试两个答案并得出结论。谢谢
【解决方案2】:

这可以做到,并且您当前的方法是一个定义良好的设计模式,尽管大多数实现使 Clone 成为抽象虚拟方法并在所有子类中覆盖它。

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( );
    }
}

由于您使用的是 C#,因此您可以使用 Activator 类。您可以使用默认实现将 Clone 方法设为虚拟(不是 === 抽象)。

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

编辑 - 如果您的所有派生类中都没有默认的无参数构造函数,则可以在Activator.CreateInstance 方法中添加参数

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

对于派生类型的不同构造函数,我建议您覆盖专门针对这些类型的 Clone 方法,而不是使用 Clone 的默认实现。

【讨论】:

  • 最后一个示例必须将响应转换为A,就像return (A)Activator.CreateInstance(this.GetType( ));一样,因为Activator.CreateInstance返回对象
  • 这正是我想要的,我会测试它并返回消息
  • 此解决方案的问题在于它依赖于 OP 所没有的无参数构造函数。对于与您的构造函数一起使用的反射解决方案,请查看其他答案@MatiCicero
  • 没有什么能阻止您向Activator.CreateInstance 方法添加参数。我选择省略它们,因为派生类构造函数在 A 的范围内是未知的(请参阅编辑以继续......)
【解决方案3】:

虽然我喜欢 Jamiec 解决方案,但我缺少使用反射的肮脏解决方案 :)

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

【讨论】:

  • +1 表示适用于非无参数 ctor 的明显反射解决方案
  • 哦,脏了,我喜欢它:D
猜你喜欢
  • 2011-11-05
  • 1970-01-01
  • 1970-01-01
  • 2023-02-22
  • 1970-01-01
  • 2011-01-21
  • 1970-01-01
  • 2013-11-16
  • 2021-02-28
相关资源
最近更新 更多