【问题标题】:Putting custom ICloneable implementation in abstract base class将自定义 ICloneable 实现放在抽象基类中
【发布时间】:2017-02-11 18:24:08
【问题描述】:

我正在尝试在抽象基类中实现ICloneable.Clone(),这样子类就不用担心了。 该类的一个基本职责是拥有一个应该传递给克隆的内部Guid 属性——也就是说,它更像是一个“属性克隆”。这允许我克隆从存储库中获取的项目,在不更改原始项目的情况下更改其属性,然后以它可以通过 Id 识别的方式将更改的实例提交回存储库。

但我当前的实现面临一个问题:我无法创建实例来传递 Id,因为该类是抽象的!

public abstract class RepoItem : ICloneable, IEquatable<RepoItem>
{
    protected RepoItem()
    {
        Id = Guid.NewGuid();
    }

    private RepoItem(Guid id)
    {
        Id = id;
    }

    public Guid Id { get; private set; } 

    public object Clone()
    {
        return new RepoItem(Id);  // cannot create instance of abstract class
    }

    public bool Equals(RepoItem other)
    {
        return other.Id == Id;
    }
}

有没有办法解决这个问题?这是一个不错的设计吗?

【问题讨论】:

  • 无论如何你都在创建错误的类型。问题是,您不知道基类中的正确类型应该是什么。您需要创建实际运行时类型的实例 - 例如通过派生类将要实现的抽象方法。
  • 您不妨将Clone 设为抽象,因为子类会知道如何克隆自己。
  • @Luaan 你认为基于反射的方法可以吗?
  • @juharr 实际上,这可能是确保Clone 由派生类实现的最佳解决方案。仍然必须确保 Clone 被所有可以实例化的类覆盖。
  • 当然,但是为什么要使用ICloneable?只需创建一个可以克隆任何对象的通用辅助方法。如果您不想使用继承/多态,则将其作为基类的一部分是没有意义的。

标签: c# clone


【解决方案1】:

正如在 cmets 中已经解释的那样,你不能这样做......

最好的办法可能是使Clone 成为一个抽象方法(以确保克隆可用于所有派生类,尽管必须显式覆盖Clone,如果派生级别不止一层,还有更多一个级别有一个可以实例化的class。)。

在那之后,有一种复制构造函数将是要走的路:

class RepoItem : ICloneable
{
    public abstract void Clone();
    protected RepoItem(RepoItem other) { Id = other.Id; }
}

class Derived1 : RepoItem
{
    protected Derived1(Derived1 other) : base(other) 
    { 
        myField1 = other.myField1; 
    }
    public virtual object Clone() { return new Derived1(this); }

    private int myField1;
}

class Derived2 : Derived1
{
    protected Derived2(Derived2 other) : base(other) 
    { 
        myField2 = other.myField2; 
    }
    public override object Clone() { return new Derived2(this); }

    private int myField2;
}

我不确定virtualoverride 是否正确,因为我很少写这样的代码。

【讨论】:

    【解决方案2】:

    退后一步。 您根本不应该实现这个接口,所以无论是在基类中实现还是在其他完全无关紧要的地方。一开始就不要去那里。

    此界面自 2003 年以来已被弃用。请参阅:

    Why should I implement ICloneable in c#?

    了解详情。

    【讨论】:

    • 好吧,我认为这已经足够权威了;o) 谢谢!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-03
    相关资源
    最近更新 更多