D
Daniel O'Connell
From what I've read I'd argue that copy constructors are not better,
you are restricted(and damned) to loosing data when you create the copy.
Imagine a case where you recieve MyObject as a parameter, something like:
public MyObject DoSomeStuffToMyObjectWithCopy(MyObject obj)
{
MyObject newObj = new MyObject(obj);
//do something
return newObj.
}
called as:
MyDerivedObject derivedObj;
MyDerivedObject (MyDerivedObject)DoSomeStuffToMyObjectWithCopy(derivedObj);
//cast exception
consider the same case with a clone:
public MyObject DoSomeStuffToMyObjectWithCopy(MyObject obj)
{
MyObject newObj = MyObject.Clone();
//do something
return newObj.
}
called as:
MyDerivedObject derivedObj;
MyDerivedObject (MyDerivedObject)DoSomeStuffToMyObjectWithCopy(derivedObj);
//shouldn't be an issue here.
I wouldn't ever consider an object of type MyObject to be a clone or copy of
an object of type MyDerivedObject. This is much more of a conversion in my
mind rather than a copy, even if its to a similar type.
As for composition, that was in reference to Jay B. Harlows comments about
things like System.IO where Stream and the various readers often rely on
other readers derived from the same class, in essence by using composition.
feature that increases the chances of programmer mistake is irresponsible in
my mind. For example, do you know the rules for how VB or C#, for example,
resolves every possible overload scenario, or if there are differences
between them? I've run into a few surprises myself, I wouldn't be very
pleased if a language quirk takes away the ability to perform a copy. Copy
constructors themselves aren't particularly complicated, but when combined
with overload resolution rules and a large number of languages you have to
take into consideration, I would call the issue complicated at the least.
be cloning, while new MyObject(myObjectReference) just says that you are
creating a new object. There is a level of obviousness that copy
constructors don't have.
guarentee. However Clone gives you a reasonable expectation and a
polymorphic way to ensure all data is copied. Copying only the fields in the
base class is irresponsible, IMHO, and by relying on the base class
developer to provide copying you are doing just that, when you use Clone you
are relying on the implementer in the actual class, not the concrete type
you chose. I would say that implementer has a better shot at getting all of
the right fields copied, wouldn't you?
plugin system? You *NEVER* know concrete types ahead of time, only
interfaces. When you want to issue a clone call to an object that you know
only by a set of interfaces, explicit copy constructors are unable to
achieve that.
IMyDataSource src;
//I want to copy src...can't be done without Clone(or reflection, which
seems silly).
Whats the serious difference in writing a constructor:
//in MyObject
MyObject(MyObject o)
{
this.MyBaseField=o.MyBaseField;
}
//in MyDerivedObject
MyDerivedObject(MyDerivedObject o) : this(o)
{
this.MyDerivedFIeld = o.MyDerivedField);
}
and
//in MyObject
public virtual object Clone()
{
return Clone(new MyObject());
}
protected virtual Clone(MyObject o)
{
o.MyBaseField = this.MyBaseField;
}
//in MyDerivedObject
public override object Clone()
{
return Clone(new MyDerivedObject());
}
protected virtual Clone(MyObject o)
{
MyDerivedObject = o as MyDerivedObject; //not needing this line isn't
sufficent, I'm afraid
d.MyDerivedField = this.MyDerivedField
base.Clone(o)
}
flawed model for public copying. However as I showed above its not the only
way to achieve a copy. Constructors are only nessecery in the case of read
only fields...which I personally consider to be irresponsible at the
instance level in general.
copy constructors are not normal. It is aesthetics, granted, but I disagree
that it is proper to adopt something that the smaller set of the major
languages uses simply because some people feel its easier.
arguments boil down to "Its easier in languages where you are used to it",
which I find to be far more aesthetic than technical...perhaps you disagree?
That is entirely the problem. It defines the type at compile time, meaningWhat that you have read about them that leads you to believe this ? Please
give technical arguments.
Come again ? A copy constructor always defines the type which is to be
copied at compile time as part of the signature of the constructor. I have
no idea to what the term "Composition arguments" refers.
you are restricted(and damned) to loosing data when you create the copy.
Imagine a case where you recieve MyObject as a parameter, something like:
public MyObject DoSomeStuffToMyObjectWithCopy(MyObject obj)
{
MyObject newObj = new MyObject(obj);
//do something
return newObj.
}
called as:
MyDerivedObject derivedObj;
MyDerivedObject (MyDerivedObject)DoSomeStuffToMyObjectWithCopy(derivedObj);
//cast exception
consider the same case with a clone:
public MyObject DoSomeStuffToMyObjectWithCopy(MyObject obj)
{
MyObject newObj = MyObject.Clone();
//do something
return newObj.
}
called as:
MyDerivedObject derivedObj;
MyDerivedObject (MyDerivedObject)DoSomeStuffToMyObjectWithCopy(derivedObj);
//shouldn't be an issue here.
I wouldn't ever consider an object of type MyObject to be a clone or copy of
an object of type MyDerivedObject. This is much more of a conversion in my
mind rather than a copy, even if its to a similar type.
As for composition, that was in reference to Jay B. Harlows comments about
things like System.IO where Stream and the various readers often rely on
other readers derived from the same class, in essence by using composition.
Obviously its not a popularity contest, but intentionally employeeing aWithout documentation programmers are going to suffer no matter what your
methods are called. Why would anyone want to create a badly typed
constructor, and how would this differ from a badly implemented Clone()
method ? As far as "complicated language rules that not everyone is familiar
with", programming is not a popularity contest nor are copy constructors any
more complicated than any other language construct.
feature that increases the chances of programmer mistake is irresponsible in
my mind. For example, do you know the rules for how VB or C#, for example,
resolves every possible overload scenario, or if there are differences
between them? I've run into a few surprises myself, I wouldn't be very
pleased if a language quirk takes away the ability to perform a copy. Copy
constructors themselves aren't particularly complicated, but when combined
with overload resolution rules and a large number of languages you have to
take into consideration, I would call the issue complicated at the least.
Properly implemented, MyObject.Clone certainly says to me that its going toIf your opposition to copy constructors are that they are not aesthetically
pleasing to you, it is probably because you haven't used them very much. I
assume that is what you mean by "grace" in this context.
"Using a copy constructor tells me I have a copy of an object, while calling
Clone() leaves me wondering if I'll get a copy or a aggregate object, or
simply an object that takes a limited set of settings from another
object(perhaps preferences without data)."
be cloning, while new MyObject(myObjectReference) just says that you are
creating a new object. There is a level of obviousness that copy
constructors don't have.
You don't have a guarentee, of course in programming you'll never have aWhat is relevant data is determined by the designer of the classes in the
hierarchy in which the copy constructor resides. Why is Clone() any better ?
What guarantee do I have that all relevant data has been copied from the
current object and its base classes into the object I have cloned ? It is
once again a decision of the designer of the class.
guarentee. However Clone gives you a reasonable expectation and a
polymorphic way to ensure all data is copied. Copying only the fields in the
base class is irresponsible, IMHO, and by relying on the base class
developer to provide copying you are doing just that, when you use Clone you
are relying on the implementer in the actual class, not the concrete type
you chose. I would say that implementer has a better shot at getting all of
the right fields copied, wouldn't you?
Hrmm, have you ever done any loosely coupled programming? Or tried to do aInterfaces are member function contracts and do not contain data AFAIK.
See above.
plugin system? You *NEVER* know concrete types ahead of time, only
interfaces. When you want to issue a clone call to an object that you know
only by a set of interfaces, explicit copy constructors are unable to
achieve that.
IMyDataSource src;
//I want to copy src...can't be done without Clone(or reflection, which
seems silly).
Yes, however, I don't feel you have to use a constructor in *most* cases.It certainly is easier to call the base class's constructor to initialize
base class data from a copy, and initialize just the data in your own class
from a copy, than having to initialize all data in all base classes
including your own class from a copy. I believe you have to be kidding to
feel otherwise. As I also previously pointed out, there is no way to
initialize private base class data in my derived class when doing Clone()
since I have no access to it. But that is not a problem using copy
constructors since each class in hierarchy initializes its own data from
the copy used to construct the original object.
Whats the serious difference in writing a constructor:
//in MyObject
MyObject(MyObject o)
{
this.MyBaseField=o.MyBaseField;
}
//in MyDerivedObject
MyDerivedObject(MyDerivedObject o) : this(o)
{
this.MyDerivedFIeld = o.MyDerivedField);
}
and
//in MyObject
public virtual object Clone()
{
return Clone(new MyObject());
}
protected virtual Clone(MyObject o)
{
o.MyBaseField = this.MyBaseField;
}
//in MyDerivedObject
public override object Clone()
{
return Clone(new MyDerivedObject());
}
protected virtual Clone(MyObject o)
{
MyDerivedObject = o as MyDerivedObject; //not needing this line isn't
sufficent, I'm afraid
d.MyDerivedField = this.MyDerivedField
base.Clone(o)
}
It shows its not flawed when used in a protected manner, but I'd call it aI have no issue with protected copy constructors. Another poster gave me a
very good method of implementing Clone() using protected copy constructors.
That just shows me that the copy constructor technique is not flawed. That
technique is certainly a workable implementation for Clone() and the only
way to copy private data from the base class.
flawed model for public copying. However as I showed above its not the only
way to achieve a copy. Constructors are only nessecery in the case of read
only fields...which I personally consider to be irresponsible at the
instance level in general.
More of an issue of reality. In most of languages in the .NET framework,Again that is an aesthetic call. If you have programmed in a language where
copy constructors create an easy to program methodology of creating an
object based on another object of the same type, than copy constructors are
more natural than Clone().
copy constructors are not normal. It is aesthetics, granted, but I disagree
that it is proper to adopt something that the smaller set of the major
languages uses simply because some people feel its easier.
Please, before attacking me about technical merit, provide some. All yourI have explained why it is better a number of times in this thread. However
the technique of creating Clone() using a protected copy constructor is fine
with me, and does have the added attraction that once I implement it, other
objects know I am cloneable. I don't believe your own arguments have
technical merit but rely on aesthetics and "unknown" sources. Please argue
the technical issues youirself and not bring up language prejudices. I am
not supporting copy constructors because it is C++ but because it is an easy
and safe method to create an object based on another object. If it can be
abused, it is no different from an implementer of Clone() abusing that
functionality. Finally, as I have repeatedly shown, unless Clone() is
implemented using copy constructors, it is broken if base classes have
private data that need to be cloned also.
arguments boil down to "Its easier in languages where you are used to it",
which I find to be far more aesthetic than technical...perhaps you disagree?