【问题标题】:Implement copy/deepcopy on multiple base classes在多个基类上实现复制/深度复制
【发布时间】:2014-07-09 10:03:16
【问题描述】:

不确定这是否是 codeReview 帖子,但我们开始吧:

我的目标是重新实现在我们的应用程序中复制对象的方式。我们有多个基类:

CoreList<T> // for all list classes
BasicReference // for all reference classes
CoreObject // for all "normal" domain objects

所有类都继承自这些基类。现在复制方法是在CoreObject类上实现的,它将通过反射遍历对象树,查看每个属性类型并选择正确的复制类型的方法,最后总是返回CoreObject

这种方法有一些我不喜欢的问题,这就是我想改变它的原因:

  • 复制域对象后,您始终必须将其“转换回”为原始类型,例如:Animal = animal.Copy() as Animal;
  • 复制每种类型的所有逻辑都在 CoreObject 类中,即使它不应该知道其他基类。

所以我的第一次尝试是引入一个接口:

public interface IObjectCopy<out T>
{
  T Copy();
}

然后应该在所有基类上实现。然后每个类负责它被复制的方式。例如(伪代码):

public class CoreObject : IObjectCopy<CoreObject>
{
  public virtual GerCoreObject Copy() 
  { 
    foreach (var prop in properties)
    {
      if (prop.IsNoSimpleType)
      {
        (prop as IObjectCopy).Copy()
    }
  }
}

这解决了复制责任问题,此外继承的类可以自己处理复制逻辑。

不幸的是,这并没有解决返回类型,我仍然必须将它转换为正确的类型。我没有想到更好的解决方案来解决这个问题。有什么想法吗?

【问题讨论】:

    标签: c# inheritance copy polymorphism


    【解决方案1】:

    这个问题可以在OO中使用covariant return types来解决。不幸的是,C# 不支持协变返回类型,如 Java 和 C++,要求它总是破坏类型安全。

    如果不破坏 C# 中的类型安全(强制转换),这是不可能的。

    这里有两种可能的选择:

    //explicit interface implementation
    public class Animal : CoreObject, IObjectCopy<Animal>
    {
        Animal IObjectCopy<Animal>.Copy()
        {
            return (Animal) base.Copy();
        }
    }
    //does not require an explicit cast
    IObjectCopy<Animal> animalCopy = myAnimal;
    Animal copiedAnimal = animalCopy.Copy();
    
    //second option: shadow the original method and cast inside the object
    public class Animal : CoreObject, IObjectCopy<Animal>
    {
        public new Animal Copy()
        {
            return (Animal) base.Copy();
        }
    }
    Animal copy = myAnimal.Copy();
    

    使用有界量化的另一种选择:

    public class CoreObject : IObjectCopy<CoreObject>
    {
        public CoreObject Copy()
        {
            return Copy<CoreObject>();
        }
    
        protected T Copy<T>()
            where T : CoreObject, new()
        {
            T t = new T();
            //implement copy logic:
            return t;
        }
    }
    
    public class Animal : CoreObject, IObjectCopy<Animal>
    {
        public new Animal Copy()
        {
            return Copy<Animal>();
        }
    }
    

    【讨论】:

    • 顺便说一句,C# 现在支持协方差 (msdn.microsoft.com/library/ee207183.aspx)。 @derape 甚至在他的问题中使用它
    • @Archeg 但不是返回类型的协方差!
    • 你的意思是没有泛型?是的,但是使用泛型您可以完成大部分工作(例如,在我提出的解决方案中)。虽然它可能看起来有点复杂
    • @Archeg 就像维基百科链接上的例子
    • 可以使用泛型。 C 其中 T:A 和 D:C。然后 getFoo() 将为 C 返回 A,为 D 返回 B
    【解决方案2】:

    如果我理解正确,你需要Curiously recurring template pattern

    public class BaseClass<T> where T : BaseClass<T>
    {
         public virtual T Clone()
         {
             // Perform cloning with reflection.
             return clone as T;
         }
    }
    

    然后你只需将你的类定义为:

    public class EndObject : BaseClass<EndObject>
    {
    }
    
    EndObject e;
    e.Clone() // Will return EndObject type
    

    【讨论】:

    • +1,但要小心:这需要对 API 进行重大的重大更改,以支持克隆而不进行强制转换。
    • 我同意@BasBrekelmans。如果你的层次结构很简单,如果它非常复杂和通用 - 你可能会碰巧过度复杂化它。
    • 我真的很喜欢这个解决方案,但不幸的是,我们的 API 相当复杂,需要大量重构以使其适应泛型类 :-(
    猜你喜欢
    • 2021-12-12
    • 1970-01-01
    • 2020-07-28
    • 1970-01-01
    • 2010-12-02
    • 2012-05-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多