Link to home
Start Free TrialLog in
Avatar of KurtVon
KurtVon

asked on

Inheriting cloning

I'm a little looped on decongestiants at the moment, so I hope this is coherent. :-)

My problem is I have a set of classes which I need to be able to make deep copies of.  Normally this is done with the ICloneable interface and the Clone function, so I tried to do this.  The problem is the relationships between the classes.

public class A : B
{
    public A() { m_list = null };

    internal SortedArray m_list;

    public object Clone()
    {
        A a;

        // ????

        a.m_list = m_list.Clone();
    }
}

public class B : ICloneable
{
    public B() { Next = null; }

    internal B Next;

    public object Clone()
    {
      B b = new B();
      b.Next = Next.Clone;
    }
}

The problem is twofold.  The first obvious one is that I get a compiler error "The keyword new is required on 'A.Clone()' because it hides inherited member 'B.Clone()'."  I seem to be missing something since it seems that either there should be no error, or the error should be that I'm attempting to override non-virtual function.

The other problem is that I need A to clone the members of B, and still provide an object of type A at the line marked "//???".  How in the heck do I create the object to do that?  Sorry if this sounds rather lame, but I'm just not seeing it.
Avatar of Razzie_
Razzie_

For your first problem, yes, you need to use the 'new' keyword if you are inheriting the base method and overriding it.

Seconds, I'm not sure if I understand what you mean, but have you tried calling base.Clone(); in your clone method. This will call class B's clone method.

HTH,

Razzie
Avatar of KurtVon

ASKER

Wouldn't that cause a runtime error?  After all, teh B.Clone returns a new B, not a new A.  So if the A.Clone function looked like

new public object Clone()
{
    A a = (A)base.Clone();
    a.m_list = m_list.Clone();
}

The base.Clone returned an object of new B, and would therefore throw an exception.

From what I can see, what I need to do is somehow create an new object of class A, and then call the base Clone function into it.  Or maybe you just can't inherit cloning, so every cloned object must clone all base members too?

Yeah that doesn't work but I didn't mean that. I just wonder why you need to call b.Clone(). What purpose does that have? If you need to get a new clone of B as well, can't you have a property b in your A class and in the clone() method use

public new object Clone()
{
   A a = new A();
   a.b = base.Clone();
   return a;
}

Is that what you mean?

   
Avatar of KurtVon

ASKER

How would I make such a property?  B is a base class, not a member of A, so the problem is the assignment.  Also, by overriding standard inheritance with a new, what happens when something calls the A.Clone function while thinking it is pointing to a class of type B?

cloner()
{
  B b = new A();
  B otherb = b.Clone();  // Will this call B.Clone or A.Clone?
}

It just seems odd to me that the Clone function wouldn't be virtual.
You could make that property by using:

private B _b = null;

public B b
{
   get{ return this._b; }
   set{ this._b = value; }
}

when you'd use:

public new object Clone()
{
   A a = new A();
   a.b = base.Clone();
   return a;
}

the _b isntance would be set to the cloned object.
About your question:

B b = new A();
B otherb = b.Clone();  // Will this call B.Clone or A.Clone?

That would call B.Clone();
Avatar of KurtVon

ASKER

Okay, so clone is a dead end after all.

How do I do a deep copy of virtual objects, then?  Is there a standard interface?  It seems odd that the Clone function would be designed to kill further descending from an object.

Unfortunately I can't modify the library so much as to change inheritance into membership, there is just too much polymorphism in use throughout it.
From what I know Clone() returns a shallow copy by default. If you need a deep copy, you'd need to Clone() every object that is a member of the object you want to clone as well, and add the cloned members. Like:

A a = new A();
a.m_list = this.m_list.Clone();
a.someOtherObject = this.someOtherObject.Clone();
return a;
Avatar of KurtVon

ASKER

From what I read, I was under the impression Copy made a shallow copy and Clone made a deep copy.  At least, that is how it appears to work with the members of Collections.

But if Clone won't work, then I need to find a method that does.  I tried just creating my own version of the Clone function as a virtual, but it doesn't seem to work

public class A : B
{
  virtual public object myClone(ref object obj)
  {
    A a;
    if (obj == null)
        a = new A();
    else
        a = (A)obj;
    base.myClone(ref a);
    a.m_list = m_list.Clone();
    return a;
  }
}

public class B : object
{
    virtual public object myClone(ref object obj)
    {
        B b;
        if (obj == null)
            b = new B();
        else
            b = (B)obj;
        b.Next = Next.myClone(null);
        return b;
    }
}

But I keep getting a compiler error that the call to the base.myClone has some invalid arguments.

By the way, I wasn't joking about being looped on decongestiants.  I'm probably not in any condition to program right now, but the deadline is looming and I have to get this project done.  Sorry if I'm coming across a bit thick at the moment.
Hmm you can't pass a reference of class A to the base.myClone method when it takes an object as a reference. So you'd have to change it to myClone(ref B b2) or something.

also I can tell you now that b.Next = Next.myClone(null) won't work either. I doubt it will be necessary to pass them as ref parameters anyway.

Oh well it's almost 1 am here, no condition to program for me too, still I hope it helped you some :)
Avatar of KurtVon

ASKER

Sorry for the long delay.  The conjestion turned out to be pneumonia.

The parameter for myClone must be an object, since if I type it for the class it won't be overridden by the child class, which is necesary for polymorphism.  I think Im going to have to do this the ugly way, and just stream out the object to a memory stream, then read it back in.

I'm just surprised there is no proper facility for a polymorphic deep-copy function.
ASKER CERTIFIED SOLUTION
Avatar of Razzie_
Razzie_

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of KurtVon

ASKER

Sorry for the delay in answering.  I had hoped that somehow there would be a better way, but after implementing the ugly solution I have grown to actually appreciate it (plus it resulted in catching a bug in my code).