MC Emperor
MC Emperor

Reputation: 22977

Using "this" in another constructor

Suppose you have a class with this constructor:

public SomeObj(int x, int y) {
    this.x = x;
    this.y = y;
}

All good. But now if you want to clone the object, I want a constructor to accept one argument with an object from that type, so inside the constructor all (necessary) fields can be copied.

public SomeObj(SomeObj objectToClone) { ... }

But now which of the following two ways is better? What are the advantages and disadvantages (performance (byte code), readability...)?

// 1
public SomeObj(SomeObj objectToClone) {
    this.x = objectToClone.x;
    this.y = objectToClone.y;
}

// 2
public SomeObj(SomeObj objectToClone) {
    this(objectToClone.x, objectToClone.y);
}

Upvotes: 3

Views: 239

Answers (6)

Matthias Meid
Matthias Meid

Reputation: 12513

The latter does not build anymore as soon as you add another parameter, let's say z. If you'd take the first approach, you might just forget to copy z. It still builds, but doesn't work properly.

Upvotes: 1

Andrei G
Andrei G

Reputation: 1590

// 1
public SomeObj(SomeObj objectToClone) {
    this.x = objectToClone.x;
    this.y = objectToClone.y;
}

is better.

Your second option would require you to update your constructor each time you add a new parameter. Also, if you have to call that in 100 places with 100 properties to list in each constructor, it's obvious it starts loosing readability.

I can't understand why you would like to pass multiple properties of the same object as parameter instead of passing the object. There's no reason for that.

Compare these two:

public SomeObj(SomeObj objectToClone) {
    this.x = objectToClone.x;
    this.y = objectToClone.y;
    this.z = objectToClone.z;
    this.p = objectToClone.p;
    this.s = objectToClone.s;
    this.a = objectToClone.a;
    this.b = objectToClone.b;
    }

and then call SomeObj(obj) 10 times in your code.

versus SomeObj(obj.x,obj.y,obj.z,obj.p,obj.s,obj.t,obj.a,obj.b); 10 times in your code

Also, with the second option you have no guarantee that the parameters passed are what you want, so you could get something like this: SomeObj(obj.x,obj.y,obj2.z,obj3.p,0,0,-1,null);

Upvotes: 0

Ilya
Ilya

Reputation: 29683

It's not C++. Override .clone() method from Object class for copy objects. It's true way

Upvotes: 1

sch
sch

Reputation: 27506

If you use the second option, you don't have to change public SomeObj(SomeObj objectToClone) every time you change the implementation of public SomeObj(int x, int y). So it is better as it allows you to avoid duplicating code.

Upvotes: 2

Chii
Chii

Reputation: 14738

Number 2 is better. Why? because you are no longer repeating yourself, setting a member in two different constructors.

There is no performance hit really, unless the miniscule extra indirection of calling this() is going to affect you (and i doubt you can even measure this difference accurately).

Upvotes: 3

Jon Skeet
Jon Skeet

Reputation: 1499950

I would go with the latter, personally.

Where possible, I try to make exactly one constructor have a "real" body, and make all others delegate to it. That's not always possible - in particular, different constructors may need to delegate to different superconstructors - but it's nice knowing there's one place you can put extra initialization, logging, breakpoints etc which will always get hit.

Upvotes: 13

Related Questions