簡體   English   中英

如何在基類中創建對象的克隆?

[英]How do I create clone of object in base class?

我需要一個在基類中創建對象的空克隆的方法嗎? 例如:

public class ChildClass : ParentClass
{
   public ChildClass()
   {
   }
}
public class ParentClass
{
  public SomeMethod()
  {
     // I want to create an instance of the ChildClass here
  }
}

到目前為止,我們在父類中定義了一個抽象方法。 並且,所有子類都實現它們。 但是,所有實現都相同,只是類型不同。

public class ChildClass : ParentClass
{
   public ChildClass()
   {
   }
   public ParentClass CreateEmpty()
   {
      return new ChildClass();
   }
}
public class ParentClass
{
  public SomeMethod()
  {
     // I want to create an instance of the ChildClass here
     ParentClass empty = CreateEmpty();

  }
  public abstract ParentClass CreateEmpty();
}

有什么辦法可以從父類中做到這一點,這樣我就不必繼續為每個不同的子類實現相同的邏輯? 注意,可能會有更多級別的繼承(即ChildChildClass:ChildClass:ParentClass)。

如果使用反射對您來說不是問題,則可以使用Activator類來實現:


//In parent class
public ParentClass CreateEmpty()
{
    return (ParentClass)Activator.CreateInstance(this.GetType());
}

這將返回所需類型的空對象。 請注意,此方法不必是虛擬的。

另一方面,我認為您當前的方法還不錯,再多幾行代碼也不錯。

這有點實驗。 我不知道這是否會導致循環依賴。 幾個月沒有接觸C#。

public class ParentClass<T> where T : ParentClass<T>, new() { // fixed
    public ParentClass() {
        var x = new T(); // fixed, was T.new()
    }
}

public class ChildClass : ParentClass<ChildClass> {
    public ChildClass() { }
}

否則,請使用Ravadre的ReflectionCode。

您可以使用二進制序列化程序對對象進行深層克隆。

編輯:剛注意到克隆(我認為是矛盾的意思)旁邊的單詞“空”。 不管怎樣,不要把這個答案留給別人,因為其他人希望進行常規克隆,這將有助於他們找到這個問題。

我正在使用以下模式。

優點:

  • 這種模式確保了在私有和公共類中克隆的類型安全性。
  • 輸出類將始終正確。
  • 您永遠不會忘記重寫“克隆”方法。 “ MyDerivedClass”絕不會返回“ MyDerivedClass”之外的其他類。

缺點:

  • 對於一個類,您需要創建一個接口和兩個類(原型和最終)

樣品:

// Common interface for cloneable classes.
public interface IPrototype : ICloneable {
    new IPrototype Clone();
}

// Generic interface for cloneable classes.
// The 'TFinal' is finaly class (type) which should be cloned.
public interface IPrototype<TFinal> where TFinal : IPrototype<TFinal> {
    new TFinal Clone();
}

// Base class for cloneable classes.
// The 'TFinal' is finaly class (type) which should be cloned.
public abstract class PrototypeBase<TFinal> : IPrototype<TFinal> where TFinal : PrototypeBase<TFinal> {
    public TFinal Clone() {
        TFinal ret = this.CreateCloneInstance();
        if ( null == ret ) {
            throw new InvalidOperationException( "Clone instance was not created." );
        }

        this.FillCloneInstance( ret );
        return ret;
    }

    // If overriden, creates new cloned instance
    protected abstract TFinal CreateCloneInstance();

    // If overriden, fill clone instance with correct values.
    protected abstract void FillCloneInstance( TFinal clone );

    IPrototype IPrototype.Clone() { return this.Clone(); }
    object ICloneable.Clone() { return this.Clone(); }
}

// Common interface for standalone class.
public interface IMyStandaloneClass : IPrototype<IMyStandaloneClass> {
    string SomeText{get;set;}
    string SomeNumber{get;set;}
}

// The prototype class contains all functionality exception the clone instance creation.
public abstract class MyStandaloneClassPrototype<TFinal> : PrototypeBase<TFinal>, IMyStandaloneClass where TFinal : MyStandaloneClassPrototype<TFinal> {
    public string SomeText {get; set;}
    public int SomeNumber {get; set}

    protected override FillCloneInstance( TFinal clone ) {
        // Now fill clone with values
        clone.SomeText = this.SomeText;
        clone.SomeNumber = this.SomeNumber;
    }
}

// The sealed clas contains only functionality for clone instance creation.
public sealed class MyStandaloneClass : MyStandaloneClassPrototype<MyStandaloneClass> {
    protected override MyStandaloneClass  CreateCloneInstance() {
        return new MyStandaloneClass();
    }
}

public interface IMyExtendedStandaloneClass : IMyStandaloneClass, IPrototype<IMyExtendedStandaloneClass> {
    DateTime SomeTime {get; set;}
}

// The extended prototype of MyStandaloneClassPrototype<TFinal>.
public abstract class MyExtendedStandaloneClassPrototype<TFinal> : MyStandaloneClassPrototype<TFinal> where TFinal : MyExtendedStandaloneClassPrototype<TFinal> {
    public DateTime SomeTime {get; set;}

    protected override FillCloneInstance( TFinal clone ) {
        // at first, fill the base class members
        base.FillCloneInstance( clone );

        // Now fill clone with values
        clone.SomeTime = this.SomeTime;
    }
}

public sealed class MyExtendedStandaloneClass : MyExtendedStandaloneClassPrototype<TFinal> {
    protected override MyExtendedStandaloneClass CreateCloneInstance() {
        return new MyExtendedStandaloneClass 
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM