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.
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.
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?
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?
public new object Clone()
{
A a = new A();
a.b = base.Clone();
return a;
}
Is that what you mean?
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.
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();
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();
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.
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;
A a = new A();
a.m_list = this.m_list.Clone();
a.someOtherObject = this.someOtherObject.Clone
return a;
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.
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 :)
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 :)
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.
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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).
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