Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #34468 > unrolled thread

Re: Are you sure, Mr. Gosling?

Started byArne Vajhøj <arne@vajhoej.dk>
First post2016-06-04 15:27 -0400
Last post2016-06-06 21:18 -0400
Articles 20 on this page of 29 — 8 participants

Back to article view | Back to comp.lang.java.programmer

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: Are you sure, Mr. Gosling? Arne Vajhøj <arne@vajhoej.dk> - 2016-06-04 15:27 -0400
    Re: Are you sure, Mr. Gosling? Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-04 16:43 -0400
      Re: Are you sure, Mr. Gosling? Arne Vajhøj <arne@vajhoej.dk> - 2016-06-04 18:44 -0400
        Re: Are you sure, Mr. Gosling? Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-05 08:05 -0400
          Re: Are you sure, Mr. Gosling? Arne Vajhøj <arne@vajhoej.dk> - 2016-06-05 08:31 -0400
          Re: Are you sure, Mr. Gosling? Eric Douglas <e.d.programmer@gmail.com> - 2016-06-06 05:22 -0700
            Re: Are you sure, Mr. Gosling? Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-06 09:00 -0400
              Re: Are you sure, Mr. Gosling? v_borchert@despammed.com (Volker Borchert) - 2016-06-06 16:06 +0000
                Re: Are you sure, Mr. Gosling? Robert Klemme <shortcutter@googlemail.com> - 2016-06-06 22:56 +0200
                  Re: Are you sure, Mr. Gosling? Eric Douglas <e.d.programmer@gmail.com> - 2016-06-07 05:08 -0700
                    Re: Are you sure, Mr. Gosling? Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-07 08:41 -0400
                      Re: Are you sure, Mr. Gosling? Martin Gregorie <martin@address-in-sig.invalid> - 2016-06-07 13:14 +0000
                      Re: Are you sure, Mr. Gosling? Eric Douglas <e.d.programmer@gmail.com> - 2016-06-07 06:30 -0700
                    Re: Are you sure, Mr. Gosling? Robert Klemme <shortcutter@googlemail.com> - 2016-06-07 19:10 +0200
                      Re: Are you sure, Mr. Gosling? Eric Douglas <e.d.programmer@gmail.com> - 2016-06-07 10:22 -0700
                        Re: Are you sure, Mr. Gosling? Mike Amling <mamling@chaff.us> - 2016-06-07 15:31 -0500
                          Re: Are you sure, Mr. Gosling? Eric Douglas <e.d.programmer@gmail.com> - 2016-06-08 06:31 -0700
                            Re: Are you sure, Mr. Gosling? Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-08 10:41 -0400
                              Re: Are you sure, Mr. Gosling? Eric Douglas <e.d.programmer@gmail.com> - 2016-06-08 10:21 -0700
                                Re: Are you sure, Mr. Gosling? Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-08 14:10 -0400
                            Re: Are you sure, Mr. Gosling? Robert Klemme <shortcutter@googlemail.com> - 2016-06-08 20:54 +0200
                              Re: Are you sure, Mr. Gosling? Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-08 16:36 -0400
                                Re: Are you sure, Mr. Gosling? Robert Klemme <shortcutter@googlemail.com> - 2016-06-08 23:11 +0200
                              Re: Are you sure, Mr. Gosling? Lew <lewbloch@gmail.com> - 2016-06-10 12:20 -0700
                                Re: Are you sure, Mr. Gosling? Robert Klemme <shortcutter@googlemail.com> - 2016-06-14 19:10 +0200
                        Re: Are you sure, Mr. Gosling? Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-07 17:12 -0400
                          Re: Are you sure, Mr. Gosling? Robert Klemme <shortcutter@googlemail.com> - 2016-06-07 23:25 +0200
                        Re: Are you sure, Mr. Gosling? Arne Vajhøj <arne@vajhoej.dk> - 2016-06-07 17:33 -0400
            Re: Are you sure, Mr. Gosling? Arne Vajhøj <arne@vajhoej.dk> - 2016-06-06 21:18 -0400

Page 1 of 2  [1] 2  Next page →


#34468 — Re: Are you sure, Mr. Gosling?

FromArne Vajhøj <arne@vajhoej.dk>
Date2016-06-04 15:27 -0400
SubjectRe: Are you sure, Mr. Gosling?
Message-ID<niva2t$13sk$1@gioia.aioe.org>
On 6/4/2016 2:01 PM, Stefan Ram wrote:
>   There is this famous book »The Java Programming Language,
>   Fourth Edition« by James Gosling et al.
>
>   In it, it is written about the »idiom of copy constructor«:
>
>       »This idiom is not used much within the Java class
>       libraries, because the preferred way to make a direct
>       copy of an object is by using the clone method.«
>
>   Are you sure about this, Mr. Gosling?

I do not remember ever to have written a class with a constructor
with a single argument of same type.

And the only example that I can remember having seen
is java.lang.String. And usage of that is usually a code
smell.

I do remember several Java library classes implementing
Cloneable (most relevant probably collection classes).

And I have implemented Cloneable occasionally myself.

So to me the claim seems very plausible. It fits with
what I have used of Java library and what I have used myself.
That does not really prove anything, but I would not blink
if I had read that.

Arne



[toc] | [next] | [standalone]


#34473

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2016-06-04 16:43 -0400
Message-ID<nivehs$9e0$1@dont-email.me>
In reply to#34468
On 6/4/2016 3:27 PM, Arne Vajhøj wrote:
> On 6/4/2016 2:01 PM, Stefan Ram wrote:
>>   There is this famous book »The Java Programming Language,
>>   Fourth Edition« by James Gosling et al.
>>
>>   In it, it is written about the »idiom of copy constructor«:
>>
>>       »This idiom is not used much within the Java class
>>       libraries, because the preferred way to make a direct
>>       copy of an object is by using the clone method.«
>>
>>   Are you sure about this, Mr. Gosling?

     Why ask here?  Do you think he reads this newsgroup?

> I do not remember ever to have written a class with a constructor
> with a single argument of same type.

     I've done it, but not very often.  Usually it's when the class is
mutable (for what seem to be good reasons) but I need an instance that
won't be mutated:

	class MyClass {

	    private final List<Thing> things = new ArrayList<>();

	    public void rememberThing(Thing thing) {
	        // Don't let the Thing change after I've remembered it.
	        things.add(new Thing(thing));
	    }

	    public Thing getThingAtIndex(int index) {
	        // Don't expose a remembered Thing to possible change.
	        return new Thing(things.get(index));
	    }

	    ...
	}

> And the only example that I can remember having seen
> is java.lang.String. And usage of that is usually a code
> smell.

     Well, the JavaDoc suggests that any class implementing Collection
ought to provide a constructor that takes a Collection argument.  So
we could *almost* say that ArrayList has a constructor that takes a
(slightly disguised) ArrayList as its argument.  Similar remarks apply
to Map.

     FWIW, Joshua Bloch appears to disagree with Gosling et al.  From
"Effective Java:"

	Is all this complexity [of implementing Cloneable] really
	necessary?  Rarely.  [...]  <b>you are probably better off
	providing some other means of object copying or simply not
	providing the capability.</b> [emphasis his]

	<b>A fine approach to object copying is to provide a <i>copy
	constructor</i>. [...]</b> [emphasis and italics his]

	The copy constructor approach and its static factory variant
	have many advantages over Cloneable/clone [...]

     So: Who ya gonna trust?  The guy who thought unsigned integers
were "too complex" or the guy who invented collections?

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#34474

FromArne Vajhøj <arne@vajhoej.dk>
Date2016-06-04 18:44 -0400
Message-ID<nivlkk$1mm2$1@gioia.aioe.org>
In reply to#34473
On 6/4/2016 4:43 PM, Eric Sosman wrote:
> On 6/4/2016 3:27 PM, Arne Vajhøj wrote:
>> I do not remember ever to have written a class with a constructor
>> with a single argument of same type.
>
>     I've done it, but not very often.  Usually it's when the class is
> mutable (for what seem to be good reasons) but I need an instance that
> won't be mutated:

>> And the only example that I can remember having seen
>> is java.lang.String. And usage of that is usually a code
>> smell.
>
>     Well, the JavaDoc suggests that any class implementing Collection
> ought to provide a constructor that takes a Collection argument.  So
> we could *almost* say that ArrayList has a constructor that takes a
> (slightly disguised) ArrayList as its argument.  Similar remarks apply
> to Map.

:-)

>     FWIW, Joshua Bloch appears to disagree with Gosling et al.  From
> "Effective Java:"
>
>     Is all this complexity [of implementing Cloneable] really
>     necessary?  Rarely.  [...]  <b>you are probably better off
>     providing some other means of object copying or simply not
>     providing the capability.</b> [emphasis his]
>
>     <b>A fine approach to object copying is to provide a <i>copy
>     constructor</i>. [...]</b> [emphasis and italics his]
>
>     The copy constructor approach and its static factory variant
>     have many advantages over Cloneable/clone [...]
>
>     So: Who ya gonna trust?  The guy who thought unsigned integers
> were "too complex" or the guy who invented collections?

But that is a slightly different discussion.

Q1: Does Java mostly use Cloneable instead of copy constructor?

A1: Unless we count your *almost* copy constructor then I would
say YES as an observable fact.

Q2: Should Java use use Cloneable or copy constructor?

A2: <this can be argued>

Arne

[toc] | [prev] | [next] | [standalone]


#34477

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2016-06-05 08:05 -0400
Message-ID<nj14i9$ufe$1@dont-email.me>
In reply to#34474
On 6/4/2016 6:44 PM, Arne Vajhøj wrote:
> On 6/4/2016 4:43 PM, Eric Sosman wrote:
>> On 6/4/2016 3:27 PM, Arne Vajhøj wrote:
>>> I do not remember ever to have written a class with a constructor
>>> with a single argument of same type.
>>
>>     I've done it, but not very often.  Usually it's when the class is
>> mutable (for what seem to be good reasons) but I need an instance that
>> won't be mutated:
>
>>> And the only example that I can remember having seen
>>> is java.lang.String. And usage of that is usually a code
>>> smell.
>>
>>     Well, the JavaDoc suggests that any class implementing Collection
>> ought to provide a constructor that takes a Collection argument.  So
>> we could *almost* say that ArrayList has a constructor that takes a
>> (slightly disguised) ArrayList as its argument.  Similar remarks apply
>> to Map.
>
> :-)
>
>>     FWIW, Joshua Bloch appears to disagree with Gosling et al.  From
>> "Effective Java:"
>>
>>     Is all this complexity [of implementing Cloneable] really
>>     necessary?  Rarely.  [...]  <b>you are probably better off
>>     providing some other means of object copying or simply not
>>     providing the capability.</b> [emphasis his]
>>
>>     <b>A fine approach to object copying is to provide a <i>copy
>>     constructor</i>. [...]</b> [emphasis and italics his]
>>
>>     The copy constructor approach and its static factory variant
>>     have many advantages over Cloneable/clone [...]
>>
>>     So: Who ya gonna trust?  The guy who thought unsigned integers
>> were "too complex" or the guy who invented collections?
>
> But that is a slightly different discussion.
>
> Q1: Does Java mostly use Cloneable instead of copy constructor?
>
> A1: Unless we count your *almost* copy constructor then I would
> say YES as an observable fact.
>
> Q2: Should Java use use Cloneable or copy constructor?
>
> A2: <this can be argued>

     Gosling et al. vote for Cloneable:
	"[...] the preferred way to make a direct copy of an object
	 is by using the clone method."

     Bloch votes against it:
	"The copy constructor approach and its static factory variant
	have many advantages over Cloneable/clone [...]"

... so it seems to me to be exactly the same discussion.

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#34478

FromArne Vajhøj <arne@vajhoej.dk>
Date2016-06-05 08:31 -0400
Message-ID<nj163k$1h38$1@gioia.aioe.org>
In reply to#34477
On 6/5/2016 8:05 AM, Eric Sosman wrote:
> On 6/4/2016 6:44 PM, Arne Vajhøj wrote:
>> But that is a slightly different discussion.
>>
>> Q1: Does Java mostly use Cloneable instead of copy constructor?
>>
>> A1: Unless we count your *almost* copy constructor then I would
>> say YES as an observable fact.
>>
>> Q2: Should Java use use Cloneable or copy constructor?
>>
>> A2: <this can be argued>
>
>     Gosling et al. vote for Cloneable:
>     "[...] the preferred way to make a direct copy of an object
>      is by using the clone method."
>
>     Bloch votes against it:
>     "The copy constructor approach and its static factory variant
>     have many advantages over Cloneable/clone [...]"
>
> ... so it seems to me to be exactly the same discussion.

Hmmmm.

[...] is a different discussion.

[...] says "This idiom is not used much within the Java class
libraries"

Very poor quoting!

Arne

[toc] | [prev] | [next] | [standalone]


#34492

FromEric Douglas <e.d.programmer@gmail.com>
Date2016-06-06 05:22 -0700
Message-ID<1eb77568-ae31-4316-ac21-a33db79c5aa4@googlegroups.com>
In reply to#34477
On Sunday, June 5, 2016 at 8:05:40 AM UTC-4, Eric Sosman wrote:
>      Gosling et al. vote for Cloneable:
>      Bloch votes against it:

So what's the verdict, I have a class with a copy constructor, should I change it to be Cloneable?

[toc] | [prev] | [next] | [standalone]


#34496

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2016-06-06 09:00 -0400
Message-ID<nj3s6h$l08$1@dont-email.me>
In reply to#34492
On 6/6/2016 8:22 AM, Eric Douglas wrote:
> On Sunday, June 5, 2016 at 8:05:40 AM UTC-4, Eric Sosman wrote:
>>      Gosling et al. vote for Cloneable:
>>      Bloch votes against it:
>
> So what's the verdict, I have a class with a copy constructor, should I change it to be Cloneable?

     If the vote in the Electoral College is a tie, the President
is elected by the House of Representatives.

     (In other words, make your own choice.  For myself, I've implemented
several classes with copy constructors and zero classes with Cloneable.
YMMV.)

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#34499

Fromv_borchert@despammed.com (Volker Borchert)
Date2016-06-06 16:06 +0000
Message-ID<nj471k$f77$2@Gaia.teknon.de>
In reply to#34496
Eric Sosman wrote:
> On 6/6/2016 8:22 AM, Eric Douglas wrote:
> > On Sunday, June 5, 2016 at 8:05:40 AM UTC-4, Eric Sosman wrote:
> >>      Gosling et al. vote for Cloneable:
> >>      Bloch votes against it:
> >
> > So what's the verdict, I have a class with a copy constructor, should I change it to be Cloneable?
> 
>      If the vote in the Electoral College is a tie, the President
> is elected by the House of Representatives.
> 
>      (In other words, make your own choice.  For myself, I've implemented
> several classes with copy constructors and zero classes with Cloneable.
> YMMV.)

A point for copy ctor or a factory method might be that you can
follow the old advicte to "be generous in what you accept", e.g.
have MyFancyListImpl(IMyFancyList)

-- 

"I'm a doctor, not a mechanic." Dr Leonard McCoy <mccoy@ncc1701.starfleet.fed>
"I'm a mechanic, not a doctor." Volker Borchert  <v_borchert@despammed.com>

[toc] | [prev] | [next] | [standalone]


#34503

FromRobert Klemme <shortcutter@googlemail.com>
Date2016-06-06 22:56 +0200
Message-ID<drm6bcFhke1U1@mid.individual.net>
In reply to#34499
On 06.06.2016 18:06, Volker Borchert wrote:
> Eric Sosman wrote:
>> On 6/6/2016 8:22 AM, Eric Douglas wrote:
>>> On Sunday, June 5, 2016 at 8:05:40 AM UTC-4, Eric Sosman wrote:
>>>>       Gosling et al. vote for Cloneable:
>>>>       Bloch votes against it:
>>>
>>> So what's the verdict, I have a class with a copy constructor, should I change it to be Cloneable?
>>
>>       If the vote in the Electoral College is a tie, the President
>> is elected by the House of Representatives.
>>
>>       (In other words, make your own choice.  For myself, I've implemented
>> several classes with copy constructors and zero classes with Cloneable.
>> YMMV.)
>
> A point for copy ctor or a factory method might be that you can
> follow the old advicte to "be generous in what you accept", e.g.
> have MyFancyListImpl(IMyFancyList)

This whole discussion feels slightly peculiar to me because a copy 
constructor and clone() serve different purposes.  Method clone() 
creates a new object of same type and equivalent state, depending on the 
implementation of clone() of course - but this is the intended way to go 
about things.  So this actually creates a copy of the instance.

The infamous "copy constructor" usually has a single parameter of the 
same type (sometimes superclass or interface) but will also happily 
accept any subclass instance of the argument type.  If implemented with 
"copy" logic the best this will do is copy the state of the argument 
that is relevant to this class.  It is not guaranteed to create a copy 
of the other instance.  The central point of this type of object 
creation is that calling code is in control of the resulting object's type.

Both have their merit, but different usage.  There may be some overlap 
but when I need an exact copy, I'd go for clone() whereas when I need to 
control the type (e.g. as often the case with all the collection 
classes) I'd obviously pick a "copy" constructor.

Kind regards

	robert

-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

[toc] | [prev] | [next] | [standalone]


#34523

FromEric Douglas <e.d.programmer@gmail.com>
Date2016-06-07 05:08 -0700
Message-ID<5c864ac4-9634-4c88-9d6b-d14dbf3b3886@googlegroups.com>
In reply to#34503
On Monday, June 6, 2016 at 4:56:24 PM UTC-4, Robert Klemme wrote:
> The infamous "copy constructor" usually has a single parameter of the 
> same type (sometimes superclass or interface) but will also happily 
> accept any subclass instance of the argument type.  If implemented with 
> "copy" logic the best this will do is copy the state of the argument 
> that is relevant to this class.  It is not guaranteed to create a copy 
> of the other instance.  The central point of this type of object 
> creation is that calling code is in control of the resulting object's type.

So the copy constructor is preferable?  I aim to get a custom class to copy itself, and I want a class extending that class to copy itself..

[toc] | [prev] | [next] | [standalone]


#34525

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2016-06-07 08:41 -0400
Message-ID<nj6fep$7je$1@dont-email.me>
In reply to#34523
On 6/7/2016 8:08 AM, Eric Douglas wrote:
> On Monday, June 6, 2016 at 4:56:24 PM UTC-4, Robert Klemme wrote:
>> The infamous "copy constructor" usually has a single parameter of the
>> same type (sometimes superclass or interface) but will also happily
>> accept any subclass instance of the argument type.  If implemented with
>> "copy" logic the best this will do is copy the state of the argument
>> that is relevant to this class.  It is not guaranteed to create a copy
>> of the other instance.  The central point of this type of object
>> creation is that calling code is in control of the resulting object's type.
>
> So the copy constructor is preferable?  I aim to get a custom class to copy itself, and I want a class extending that class to copy itself..

     *I* prefer copy constructors over Cloneable implementations, but not
everyone does.  As has already been pointed out, Experts Disagree.

     Here's something to keep in mind, though: Copying something seldom
"advances the computation" very much.  It doesn't create new information
(not very much, anyhow), so the time and memory spent copying doesn't
"add value" (much).  Why, then, do we want to copy?  I can think of
three reasons; perhaps you can think of others:

     - We need "defensive copies" of mutable objects.  It seems to me
       that this is a weakness of Java, but it's a weakness that's
       not going away, so ...

     - We don't really want "copies," but "objects in a known initial
       state" that we then intend to modify independently.  Factory
       methods (or better-parameterized constructors) might serve as
       alternatives to copying.

     - We actually need distinct instances of objects in identical
       state, like `new String("hello")' or `new Integer(42)'.  This
       strikes me as a possible but unlikely scenario, one that ought
       to raise an eyebrow and perhaps prompt a redesign.  (Someone
       else called this a "code smell.")

     In short, although I happen to prefer copy constructors, I write
them only rarely.  Copying, however you do it, is if not a code smell
then at least a code whiff.

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#34526

FromMartin Gregorie <martin@address-in-sig.invalid>
Date2016-06-07 13:14 +0000
Message-ID<nj6hb9$9hu$2@dont-email.me>
In reply to#34525
On Tue, 07 Jun 2016 08:41:54 -0400, Eric Sosman wrote:

>      - We don't really want "copies," but "objects in a known initial
>        state" that we then intend to modify independently.  Factory
>        methods (or better-parameterized constructors) might serve as
>        alternatives to copying.
>
Agreed, and I do that with the better constructor. 

I can't remember when I last copied or cloned an existing instance, this 
despite my last major effort (a club's rostering editor) typically having 
around 5200 instances of its most numerous Duty class - the exact number 
depending on the number of days in the season and the number of 
volunteers to be rostered.
  

-- 
martin@   | Martin Gregorie
gregorie. | Essex, UK
org       |

[toc] | [prev] | [next] | [standalone]


#34529

FromEric Douglas <e.d.programmer@gmail.com>
Date2016-06-07 06:30 -0700
Message-ID<c53a4b87-7ac6-4eab-8617-05b6c187e9ff@googlegroups.com>
In reply to#34525
On Tuesday, June 7, 2016 at 8:42:15 AM UTC-4, Eric Sosman wrote:
>      - We don't really want "copies," but "objects in a known initial
>        state" that we then intend to modify independently.  Factory
>        methods (or better-parameterized constructors) might serve as
>        alternatives to copying.

One example where I use a copy constructor is in a custom class which extends JTable.  I have custom column definitions, and a custom class defining the properties of every cell.  When I assign new column definitions I load an array of default properties for a table row using these cell objects.  When I add a new row I start by cloning the defaults.

[toc] | [prev] | [next] | [standalone]


#34540

FromRobert Klemme <shortcutter@googlemail.com>
Date2016-06-07 19:10 +0200
Message-ID<drodg0FejbU1@mid.individual.net>
In reply to#34523
On 07.06.2016 14:08, Eric Douglas wrote:
> On Monday, June 6, 2016 at 4:56:24 PM UTC-4, Robert Klemme wrote:
>> The infamous "copy constructor" usually has a single parameter of the
>> same type (sometimes superclass or interface) but will also happily
>> accept any subclass instance of the argument type.  If implemented with
>> "copy" logic the best this will do is copy the state of the argument
>> that is relevant to this class.  It is not guaranteed to create a copy
>> of the other instance.  The central point of this type of object
>> creation is that calling code is in control of the resulting object's type.
>
> So the copy constructor is preferable?

That is not what I said.

> I aim to get a custom class to copy itself, and I want a class
 > extending that class to copy itself..

That sounds more like a use case for clone() to me as it seems to stress 
that the original type is preserved.  It really depends on the usage.

Kind regards

	robert


-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

[toc] | [prev] | [next] | [standalone]


#34541

FromEric Douglas <e.d.programmer@gmail.com>
Date2016-06-07 10:22 -0700
Message-ID<746532a2-c6db-4d58-afc0-1cc57440eff5@googlegroups.com>
In reply to#34540
On Tuesday, June 7, 2016 at 1:10:36 PM UTC-4, Robert Klemme wrote:
> That sounds more like a use case for clone() to me as it seems to stress 
> that the original type is preserved.  It really depends on the usage.

Maybe I'm getting confused then.  I thought clone() sounded wrong because it should return an instance of that class, so if you extend the class and call super.clone it gets an instance of the base class?  If your extended class needs to return an instance of itself, which needs to copy all the same values as the super class plus a few more...

example:
public class BaseClass{
private Obj1 obj1;
private Obj2 obj2;
public BaseClass(final BaseClass copyMe) {
setObj1(copyMe.getObj1());
setObj2(copyMe.getObj2());
}
public Obj1 getObj1(){
return obj1;
}
public Obj2 getObj2(){
return obj2;
}
public void setObj1(final Obj1 newObj){
obj1=newObj;
}
public void setObj2(final Obj2 newObj){
obj2=newObj;
}
}
public class ExtendedClass extends BaseClass{
private Obj3 obj3;
public ExtendedClass(final ExtendedClass copyMe){
super(copyMe);
setObj3(copyMe.getObj3());
}
public Obj3 getObj3(){
return obj3;
}
public void setObj3(final Obj3 newObj){
obj3=newObj;
}
}

How would you do the clone()?

[toc] | [prev] | [next] | [standalone]


#34543

FromMike Amling <mamling@chaff.us>
Date2016-06-07 15:31 -0500
Message-ID<nj7asv$j9j$1@dont-email.me>
In reply to#34541
On 6/7/16 12:22 PM, Eric Douglas wrote:
> On Tuesday, June 7, 2016 at 1:10:36 PM UTC-4, Robert Klemme wrote:
>> That sounds more like a use case for clone() to me as it seems to stress
>> that the original type is preserved.  It really depends on the usage.
>
> Maybe I'm getting confused then.  I thought clone() sounded wrong because it should return an instance of that class, so if you extend the class and call super.clone it gets an instance of the base class?  If your extended class needs to return an instance of itself, which needs to copy all the same values as the super class plus a few more...
>
> example:
> public class BaseClass{
> private Obj1 obj1;
> private Obj2 obj2;
> public BaseClass(final BaseClass copyMe) {
> setObj1(copyMe.getObj1());
> setObj2(copyMe.getObj2());
> }
> public Obj1 getObj1(){
> return obj1;
> }
> public Obj2 getObj2(){
> return obj2;
> }
> public void setObj1(final Obj1 newObj){
> obj1=newObj;
> }
> public void setObj2(final Obj2 newObj){
> obj2=newObj;
> }
> }
> public class ExtendedClass extends BaseClass{
> private Obj3 obj3;
> public ExtendedClass(final ExtendedClass copyMe){
> super(copyMe);
> setObj3(copyMe.getObj3());
> }
> public Obj3 getObj3(){
> return obj3;
> }
> public void setObj3(final Obj3 newObj){
> obj3=newObj;
> }
> }
>
> How would you do the clone()?

A simple shallow clone, as provided by Object.clone(), is enough for the 
above.

public class BaseClass implements Cloneable {
   private Object obj1;
   private Object obj2;
   public Object clone() {
     try {
       return super.clone();
     } catch (CloneNotSupportedException c) {
       // Not likely.
       throw new IllegalStateException();
     }
   }
   public Object getObj1(){
     return obj1;
   }
   public Object getObj2(){
     return obj2;
   }
   public void setObj1(final Object newObj){
     obj1=newObj;
   }
   public void setObj2(final Object newObj){
     obj2=newObj;
   }
}
class ExtendedClass extends BaseClass{
   private Object obj3;
   public Object getObj3(){
     return obj3;
   }
   public void setObj3(final Object newObj){
     obj3=newObj;
   }
   public static void main(String[] args) throws
    CloneNotSupportedException {
     // Set up an example instance of each class.
     BaseClass bb=new BaseClass();
     bb.setObj1("1");
     bb.setObj2("2");
     ExtendedClass ee=new ExtendedClass();
     ee.setObj1("4");
     ee.setObj2("5");
     ee.setObj3("6");

     // Try cloning them.
     BaseClass newbie=(BaseClass)bb.clone();
     System.out.println("newbie("+newbie.getObj1()
      +","+newbie.getObj2()+")");
     ExtendedClass newie=(ExtendedClass)ee.clone();
     System.out.println("newie("+newie.getObj1()+","
      +newie.getObj2()+","+newie.getObj3()+")");
   }
}

Running ExtendedClass.main prints
newbie=(1,2)
newie=(4,5,6)

Note that while clone() is declared only in BaseClass, calling clone() 
on an instance of ExtendedClass returns an instance of ExtendedClass.

If you need obj1, obj2 and obj3 to themselves be cloned rather than just 
copied, it gets more complicated.

--Mike Amling
T2JqZWN0LmNsb25lKCkgZ2V0cyB5b3UgYSBjaGVhcCBzaGFsbG93IGNvcHku

[toc] | [prev] | [next] | [standalone]


#34564

FromEric Douglas <e.d.programmer@gmail.com>
Date2016-06-08 06:31 -0700
Message-ID<9ecc34ba-fac1-45ed-88cb-71403c7c906d@googlegroups.com>
In reply to#34543
On Tuesday, June 7, 2016 at 4:30:34 PM UTC-4, Mike Amling wrote:
> If you need obj1, obj2 and obj3 to themselves be cloned rather than just 
> copied, it gets more complicated.

By cloned you mean copied by value and by copied you mean copied by reference?

A copy constructor has the same amount of runtime/memory overhead as a clone method?

If both methods return the same object, my understanding is the copy constructor just looks cleaner if you have a lot of variables you want as default values and the clone method will copy those by default so should look cleaner if you have a lot of variables you want copied.

A copy constructor by default creates an instance of the current class.  A clone method by default creates an instance of Object, so either the clone method of the Cloneable class must cast super.clone() to it's own class, or everything that calls it's clone method must cast the result.

Defaults from clone() to consider (if we don't want these, we either need to specify the alternative in the copy constructor, or replace in the clone method on the new instance returned from super.clone()): Immutable objects get copied by value, bucket objects get copied by reference.

Running the following class:
import java.util.ArrayList;
public abstract class TestStatic {

     public static void main(final String[] args) {
          final BigCat c1 = new BigCat();
          c1.setVar1(7);
          c1.setVar2(5);
          final ArrayList test = new ArrayList();
          test.add("one");
          c1.setA1(test);
          final Cat c2 = c1.clone();
          c1.setVar1(9);
          System.out.println(c2.getVar1());
          // doesn't work unless clone result is cast to BigCat
          // System.out.println(c2.getVar2());
          test.add("two");
          System.out.println(c2.getA1());
          // returns a BigCat without cast
          System.out.println(c2.getClass());
     }
     public static class Cat implements Cloneable {

          private Integer var1 = 1;
          private ArrayList a1 = null;

          @Override
          public Cat clone() {
               try {
                    return (Cat) super.clone();
               } catch (final CloneNotSupportedException c) {
                    // Not likely.
                    throw new IllegalStateException();
               }
          }

          ArrayList getA1() {
               return a1;
          }

          void setA1(final ArrayList newArray) {
               a1 = newArray;
          }

          Integer getVar1() {
               return var1;
          }

          void setVar1(final Integer newVar) {
               var1 = newVar;
          }
     }

     public static class BigCat extends Cat {

          private Integer var2 = 1;

          Integer getVar2() {
               return var2;
          }

          void setVar2(final Integer newVar) {
               var2 = newVar;
          }
     }
}

gets the following output:
7
[one, two]
class com.blockhouse.javatest.utils.TestStatic$BigCat

[toc] | [prev] | [next] | [standalone]


#34569

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2016-06-08 10:41 -0400
Message-ID<nj9arf$l3v$1@dont-email.me>
In reply to#34564
On 6/8/2016 9:31 AM, Eric Douglas wrote:
> On Tuesday, June 7, 2016 at 4:30:34 PM UTC-4, Mike Amling wrote:
>> If you need obj1, obj2 and obj3 to themselves be cloned rather than just
>> copied, it gets more complicated.
>
> By cloned you mean copied by value and by copied you mean copied by reference?

     "Copied" is "whatever makes sense for the class."  For some classes
it makes sense for the "copy" to have the same field values as the
original; this is very likely the case if the fields are primitives or
are references to immutable objects.  If some of the original's fields
refer to mutable objects you may need to have the copy refer to copies
of those mutable objects -- but not necessarily; it all depends on what
your class "means."

> A copy constructor has the same amount of runtime/memory overhead as a clone method?

     "Probably not, except when it does.  That is to say, Yes.  Or No."

     In other words, either a constructor or a clone() method can execute
as many or as few statements as it likes, churn through as much or as
little memory as it likes, do as much I/O as it likes, query as many
web servers in Elbonia as it likes, ...

> If both methods return the same object, my understanding is the copy constructor just looks cleaner if you have a lot of variables you want as default values and the clone method will copy those by default so should look cleaner if you have a lot of variables you want copied.

     Cleanliness is in the eye of the beholder.  (So is grit.)

> A copy constructor by default creates an instance of the current class.  A clone method by default creates an instance of Object, so either the clone method of the Cloneable class must cast super.clone() to it's own class, or everything that calls it's clone method must cast the result.

     More precisely, a constructor "creates" nothing at all.  The `new'
keyword creates an object of a specified class, and then the chain of
constructors initialize that object.  (That's why Object's constructor,
for example, sometimes initializes a String and sometimes a JButton.)

     As for the "default" behavior of clone() -- Well, the "default"
behavior is to create and throw a CloneNotSupportedException.  If you
implement Cloneable and write a clone() method, that method has some
kind of behavior -- but it's hard to call it a "default" behavior.

     You may choose to specify that your clone() implementation returns
a Gizmo instead of an Object (if that's your preference), and assuming
the returned object is obtained from super.clone() then yes: At some
point along the line somebody must apply a cast.  However, I'd suggest
returning an Object instead, because that puts the fewest constraints
on the clone() methods of subclasses -- they might want to return a
non-Gizmo, and if your class' clone() returns Gizmo they'll be unable
to override it.  If your class is final, yeah, maybe then you could
have clone() return a Gizmo -- but if not, I'd strongly recommend
sticking with Object.  (It would be rather strange for a clone() to
return something of a different class than the cloned "leaf" object,
but clone() is itself rather strange, IMHO.  Stay on the safe side.)

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#34570

FromEric Douglas <e.d.programmer@gmail.com>
Date2016-06-08 10:21 -0700
Message-ID<a682cfb6-e880-481d-a9de-1be42b5d7d50@googlegroups.com>
In reply to#34569
On Wednesday, June 8, 2016 at 10:42:04 AM UTC-4, Eric Sosman wrote:
> > A copy constructor has the same amount of runtime/memory overhead as a clone method?
> 
>      "Probably not, except when it does.  That is to say, Yes.  Or No."
> 
>      In other words, either a constructor or a clone() method can execute
> as many or as few statements as it likes, churn through as much or as
> little memory as it likes, do as much I/O as it likes, query as many
> web servers in Elbonia as it likes, ...

That was to say the same overhead by default, if you put in the clone method which only returns the value of super.clone(), versus if you create a copy constructor which does nothing more than copy the values exactly the same as the super.clone is doing.  Of course the overhead is going to differ once you start adding custom logic.  As I say, the copy constructor only copies exactly what you tell it; the clone method will copy everything, then after you call super.clone() you can tell it to overwrite the default values.

>      As for the "default" behavior of clone() -- Well, the "default"
> behavior is to create and throw a CloneNotSupportedException.  If you
> implement Cloneable and write a clone() method, that method has some
> kind of behavior -- but it's hard to call it a "default" behavior.

Of course you have to override clone() or it will throw an exception by default.  The default behavior is what it does when you tell it to do only that, as in the previous sample:
@Override
public Object clone() { 
     try { 
          return super.clone(); 
     } catch (final CloneNotSupportedException c) { 
          // Not likely. 
          throw new IllegalStateException(); 
     } 
} 

>      You may choose to specify that your clone() implementation returns
> a Gizmo instead of an Object (if that's your preference), and assuming
> the returned object is obtained from super.clone() then yes: At some
> point along the line somebody must apply a cast.  However, I'd suggest
> returning an Object instead, because that puts the fewest constraints
> on the clone() methods of subclasses -- they might want to return a
> non-Gizmo, and if your class' clone() returns Gizmo they'll be unable
> to override it.  If your class is final, yeah, maybe then you could
> have clone() return a Gizmo -- but if not, I'd strongly recommend
> sticking with Object.  (It would be rather strange for a clone() to
> return something of a different class than the cloned "leaf" object,
> but clone() is itself rather strange, IMHO.  Stay on the safe side.)

example?  If my Gizmo clone returns a Gizmo it would be fine for a non-Gizmo to return a non-Gizmo as long as the non-Gizmo is an extension of a Gizmo.  Why would an extended class return anything from a clone which is not an instance of itself or it's super?  I would think the only time it makes sense to return the default Object is if something could really need to get a cloned instance as an Object not knowing or caring what it's class may be.  If you're only ever going to use a cloned Gizmo as a Gizmo it seems easier to cast it before you pass it out than to cast it on every call to the clone method if there may be multiple places to call it from.

[toc] | [prev] | [next] | [standalone]


#34573

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2016-06-08 14:10 -0400
Message-ID<nj9n32$5gt$1@dont-email.me>
In reply to#34570
On 6/8/2016 1:21 PM, Eric Douglas wrote:
>[...]
>>      You may choose to specify that your clone() implementation returns
>> a Gizmo instead of an Object (if that's your preference), and assuming
>> the returned object is obtained from super.clone() then yes: At some
>> point along the line somebody must apply a cast.  However, I'd suggest
>> returning an Object instead, because that puts the fewest constraints
>> on the clone() methods of subclasses -- they might want to return a
>> non-Gizmo, and if your class' clone() returns Gizmo they'll be unable
>> to override it.  If your class is final, yeah, maybe then you could
>> have clone() return a Gizmo -- but if not, I'd strongly recommend
>> sticking with Object.  (It would be rather strange for a clone() to
>> return something of a different class than the cloned "leaf" object,
>> but clone() is itself rather strange, IMHO.  Stay on the safe side.)
>
> example?  If my Gizmo clone returns a Gizmo it would be fine for a non-Gizmo to return a non-Gizmo as long as the non-Gizmo is an extension of a Gizmo.  Why would an extended class return anything from a clone which is not an instance of itself or it's super?  I would think the only time it makes sense to return the default Object is if something could really need to get a cloned instance as an Object not knowing or caring what it's class may be.  If you're only ever going to use a cloned Gizmo as a Gizmo it seems easier to cast it before you pass it out than to cast it on every call to the clone method if there may be multiple places to call it from.

     (Shrug.)  As I said, it would be "rather strange."  And as I've said
elsethread I personally am not a big fan of Cloneable and have never
implemented it in any of my own classes, so although I've made myself
familiar with the rules (had to fix somebody else's clone() once), my
view on how "best" to follow them should be taken with a grain of
salt.  YMMV, as they say.

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.java.programmer


csiph-web