Laden...

Klonen von Unterklassen

Erstellt von herbivore vor 19 Jahren Letzter Beitrag vor 19 Jahren 2.609 Views
herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren
Klonen von Unterklassen

Hallo Community,

ich habe folgendes Problem beim Ableiten der Klasse B von einer fremden Klasse A, die ICloneable implementiert.


public class A : ICloneable
{
   private int iA;

   public A ()
   {
      iA = 0;
   }

   public virtual Object Clone ()
   {
      A aClone = new A ();
      aClone.iA = this.iA;
      return aClone;
   }

   //...
}

public class B : A
{
   int iB;

   public B ()
   {
      iB = 0;
   }

   public override Object Clone ()
   {
      B bClone = new B ();
      // ???
   }

   //...
}

Wenn ich A.Clone () in B nicht überschreibe, bekomme ich beim Klonen eines B-Objekts (natürlich) ein Objekt vom Typ A zurückgeliefert.

Auch ich A.Clone () überschreibe, nützt mir in der Implementierung von B.Clone () der Aufruf base.Clone () nichts, weil ich ja ebenfalls ein Objekt der Oberklasse zurückbekomme.

Ich muss also in B.Clone () selbst ein Objekt der Unterklasse B erzeugen. Dann kann ich aber von dem Ursprungsobjekt (this) nicht die privaten Variablen der Oberklasse (iA) an das neue Objekt (bClone) übertragen.

Wie kann ich mich aus dem Dilemma befreien? Die Oberklassenvariablen per Reflection zu kopieren, ist ja vermutlich nicht im Sinne des Erfinders.

Vielen Dank schonmal!

herbivore

PS: Hups, ich hatte das Thema in "Wünsche und Kritik" eingestellt. Wie konnte mir denn das passieren? Sorry! Der 'Verschoben:'-Eintrag dort kann natürlich ruhig weg.

P
939 Beiträge seit 2003
vor 19 Jahren

Hi herbivore,

ich bin mir nicht sicher ob es so funktioniert. Du kannst es ja mal ausprobieren.

public class A : ICloneable {

   private int a;
   private ArrayList children;

   public A() {
      a = 0;
      children = new ArrayList();
   }

   public virtual object Clone() {

      // Flache Kopie des aktuellen Typs (A oder B) erzeugen.
      A clone = this.MemberwiseClone();

      // Um tiefe Kopien muss man sich selbst kümmern.
      clone.children = (ArrayList)this.children.Clone();

      return clone;
   }
}

public class B : A {

   private int b;
   private Hashtable lookup;

   public B() {
      b = 0;
      lookup = new Hashtable();
   }

   public override object Clone() {

      // Clone-Basisimplementierung aufrufen, liefert den Typ B.
      B clone = (B)base.Clone();

      // Das Feld b ist in base.Clone geklont worden.

      // Deep-Copy des neuen lookup-Feldes.
      clone.lookup = this.lookup.Clone();

      return clone;
   }
}

Gruss
Pulpapex

herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo Pulpapex,

ich denke, dass kann nicht hinhauen. Durch


B clone = (B)base.Clone();

wird ja nur das von base.Clone () gelieferte Objekt vom Typ A in einer Variable vom Typ B gespeichert. Es bleibt dadurch aber ein A-Objekt.

// Das Feld b ist in base.Clone geklont worden.

Wie meinst du das? Die Klasse A weiß doch gar nichts von dem Feld b und kann es somit nicht klonen. Übersehe ich was?


private Hashtable lookup;
//...
clone.lookup = this.lookup.Clone();
return clone;

Dieser Code bedeutet doch, dass b.Clone () ein Objekt vom Typ Hashtable zurückgibt. Das darf es aber laut Beschreibung von ICloneable.Clone nicht:

Das geklonte Objekt muss von demselben Typ wie die Originalinstanz oder mit dieser kompatibel sein.

Trotzdem vielen Dank! Vielleicht fällt dir oder jemand anderem ja noch was ein!

herbivore

P
939 Beiträge seit 2003
vor 19 Jahren

Ich hätte ja gedacht, dass du es mal ausprobiert. Ich selbst kann es hier leider nicht testen.

herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo Pulpapex,

sorry, ich habe mich verleiten lassen. Du hast Recht, Dein Code funktioniert.

Ich habe zum einen das MemberwiseClone in der Oberklasse übersehen und zum anderen bei dem Part mit der Hashtable schlampig gelesen Die Hashtable wird in clone.lookup gespeichert, zurückgegeben wird aber clone. Das ist natürlich nicht vom Typ Hashtable.

Trotzdem bleiben zwei Probleme:

  1. Die Oberklasse ist eine fremde Klasse. Ich habe keinen Einfluß darauf, ob sie MemberwiseClone benutzt und sie tut es leider nicht. Sie arbeitet wie in dem Beispiel die Klasse A mit new.

  2. Wenn selbst ich in der Unterklasse selbst MemberwiseClone benutzen würde, täte ich eben nicht genau das, was die Oberklasse tut (Das kommt aus dem Beispiel vielleicht nicht ganz raus). Sprich ich ignoriere bzw. umgehe den Code in A.Clone ().

herbivore