【问题标题】:Implementing a custom clone/copy capability: abstract or interface?实现自定义克隆/复制功能:抽象还是接口?
【发布时间】:2013-08-05 18:20:00
【问题描述】:

据我所知,不建议实现ICloneable (due to the fact that it does not differentiate between Deep Copy or Shallow Copy),我正在尝试确定我应该将其实现为抽象还是接口。

我觉得我的实现将基本保持不变,例如一个binary deep copy 和一个MemberwiseClone shallow copy,所以为此我觉得抽象方法是理想的。但是,我的理解也是 C# 不做多重继承,因此如果我需要使用 another 抽象类,那么我不再可以。

在这种情况下,我觉得实现自定义ICloneable(例如ICustomCloneable)会是更好的选择,但如果在许多类中实现实际上是相同的,我觉得我没有充分利用代码重用。

话虽如此,对于我的可克隆类中更重要的事情,使用接口来保持抽象继承清晰是否有效?还是有其他方法可以做到这一点?

或者,一个抽象实现另一个抽象是否有效(阅读:不臭)?这是我对绕过阻止我实现 CloneCapable 类以及另一个抽象类的单一继承的猜测,但这听起来可能是有问题的。例如:

public abstract class CloneCapable
{
  public object ShallowCopy()
  {
    // implementation
  }

  public object DeepCopy()
  {
    // implementation
  }
}

public abstract class ClassA : CloneCapable {}

// abstract-abstract since I can't do ClassB : ClassA, CloneCapable
public abstract class ClassB : ClassA {} 

【问题讨论】:

    标签: c# interface abstract-class icloneable


    【解决方案1】:

    我肯定会把它做成一个界面。原因在于,接口应该非常通用,这就是为什么我们可以实现多个接口。如果您想编写一些样板代码,那么没有什么能阻止您同时利用接口和抽象类。

    public interface ICustomCloneable<T>
    {
        T ShallowCopy();
        T DeepCopy();
    }
    
    public abstract class CustomCloneable<T> ICustomCloneable<T> where T : class
    {
        public T ShallowCopy() { return ShallowCopy(this); }
        public T DeepCopy() { return DeepCopy(this); }
    
        // static helpers
        public static object ShallowCopy(T obj) { /* boilerplate implementation */ }
        public static object DeepCopy(T obj) { /* boilerplate implementation */ }
    }
    
    
    public class ClassA : CustomCloneable<ClassA> { /* Use boilerplate functionality */ }
    public class ClassB : SomeOtherClass, ICustomCloneable<ClassB>
    {
        // implement ICustomCloneable using static helpers
        public ClassB ShallowCopy() { return CustomCloneable<ClassB>.ShallowCopy(this); }
        public ClassB DeepCopy() { return CustomCloneable<ClassB>.DeepCopy(this); }
    }
    

    我在这里使用了泛型,但你没有理由需要......甚至可能不希望这样做。这种方法允许您编写样板代码,但不会被它束缚

    public class ClassC : ICustomCloneable<ClassC>
    {
        public ClassC ShallowCopy() { /* Do special cloning for ClassC */ }
        public ClassC DeepCopy() { /* Do special cloning for ClassC */ }
    }
    

    【讨论】:

    • 伟大的洞察力,我很感激。
    【解决方案2】:

    我认为创建一个界面是要走的路,但后来我找到了this 问题和第一个答案。这是进行克隆的好方法,但我认为 Custom Extension Method 可能会很好,所以我根据第一篇文章和 MS 帮助页面中的代码编写了闲置代码:

    一些可以玩的类:

    [Serializable]
    public abstract class Base
    {
        public abstract int m1();
    }
    
    [Serializable]
    public class derived : Base
    {
        public int a = 42;
        public override int m1()
        {
            throw new NotImplementedException();
        }
    }
    

    具有基于两个链接的代码示例的扩展方法的类

    //Extension methods must be defined in a static class 
    public static class StringExtension
    {
        // This is the extension method. 
        // The first parameter takes the "this" modifier
        // and specifies the type for which the method is defined. 
        public static T MyCloneExtension<T>(this T t)
        {
            // Code in this function was copied from https://stackoverflow.com/questions/78536/deep-cloning-objects-in-c-sharp
            if (!typeof(T).IsSerializable)
            {
                throw new ArgumentException("The type must be serializable.", "source");
            }
    
            // Don't serialize a null object, simply return the default for that object
            if (Object.ReferenceEquals(t, null))
            {
                return default(T);
            }
    
            IFormatter formatter = new BinaryFormatter();
            Stream stream = new MemoryStream();
            using (stream)
            {
                formatter.Serialize(stream, t);
                stream.Seek(0, SeekOrigin.Begin);
                return (T)formatter.Deserialize(stream);
            }
        }
    }
    

    最后是一个克隆对象的调用

    derived d = new derived();
    derived d2 = d.MyCloneExtension<derived>();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-15
      • 2016-06-27
      • 2012-09-12
      • 1970-01-01
      • 2010-12-23
      • 2012-08-04
      • 2010-12-14
      相关资源
      最近更新 更多