Solved

Inheriting cloning

Posted on 2004-10-27
249 Views
Last Modified: 2010-04-15
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.
0
Question by:KurtVon
    12 Comments
     
    LVL 8

    Expert Comment

    by: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
    0
     
    LVL 11

    Author Comment

    by:KurtVon
    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
     
    LVL 8

    Expert Comment

    by:Razzie_
    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
     
    LVL 11

    Author Comment

    by:KurtVon
    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
     
    LVL 8

    Expert Comment

    by:Razzie_
    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
     
    LVL 11

    Author Comment

    by:KurtVon
    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
     
    LVL 8

    Expert Comment

    by:Razzie_
    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
     
    LVL 11

    Author Comment

    by:KurtVon
    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
     
    LVL 8

    Expert Comment

    by:Razzie_
    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
     
    LVL 11

    Author Comment

    by:KurtVon
    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
     
    LVL 8

    Accepted Solution

    by:
    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
     
    LVL 11

    Author Comment

    by:KurtVon
    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

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    IT, Stop Being Called Into Every Meeting

    Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

    Introduction This article series is supposed to shed some light on the use of IDisposable and objects that inherit from it. In essence, a more apt title for this article would be: using (IDisposable) {}. I’m just not sure how many people would ge…
    Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
    With the advent of Windows 10, Microsoft is pushing a Get Windows 10 icon into the notification area (system tray) of qualifying computers. There are many reasons for wanting to remove this icon. This two-part Experts Exchange video Micro Tutorial s…
    Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

    884 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    19 Experts available now in Live!

    Get 1:1 Help Now