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.
LVL 11
KurtVonAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Razzie_Commented:
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
0
KurtVonAuthor Commented:
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?

0
Razzie_Commented:
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?

   
0
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

KurtVonAuthor Commented:
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.
0
Razzie_Commented:
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();
0
KurtVonAuthor Commented:
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.
0
Razzie_Commented:
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;
0
KurtVonAuthor Commented:
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.
0
Razzie_Commented:
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 :)
0
KurtVonAuthor Commented:
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.
0
Razzie_Commented:
I concur. If you decide on doing it the ugly way, take a look at http://www.codeguru.com/forum/showthread.php?t=242411 since it might give you some ideas.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
KurtVonAuthor Commented:
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).
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.