From: The87Boy on
I am trying to construct a superclass as itself like this:

public Parent(Parent parent) {

// Set this class as itself
this = parent;
}

But it is not allowed by the compiler, but do I have to set all
variables like this:

public Parent(Parent parent) {

// Set this class as itself
this.id = parent.getID();
this.cclass = parent.getCClass();
}

Or are there any easier way?
From: Marcin Rzeźnicki on
On 15 Lis, 13:51, The87Boy <the87...(a)gmail.com> wrote:
> I am trying to construct a superclass as itself like this:
>
>     public Parent(Parent parent) {
>
>         // Set this class as itself
>         this = parent;
>     }
>
> But it is not allowed by the compiler, but do I have to set all
> variables like this:
>
>     public Parent(Parent parent) {
>
>         // Set this class as itself
>         this.id = parent.getID();
>         this.cclass = parent.getCClass();
>     }
>
> Or are there any easier way?

Not really. Depending on your needs you might try to implement
Clonable and clone parent, but still you will have to decide how to
treat reference fields (clone is shallow). Probably, you will end up
cloning all references as well so no real savings in typing here.
Additional casts can also be cumbersome. Cloning is also incompatible
with final fields. Another trick is to serialize parent and recreate
(deserialize) your object from the resulting stream, but personally I
find that ugly. So I'd just leave it as you've done it.
From: markspace on
The87Boy wrote:

> Or are there any easier way?

First, I feel obliged to point out that this technically does what you
wrote in you first example.

public static void main( String[] args )
{
Parent parent = new Parent();
Parent parent2 = parent;
}

Just in case that's actually what you need. If you need to go with
cloning, here's a template you can use. Not the best example, perhaps,
but I think it's largely self-explanatory. Note that you MUST call
super.clone() for the clone() method to work correctly, because this
class is not final. Note also that final fields can be used, they just
can't be changed.

public class Parent implements Cloneable {

int a = 42;
final int b=0;
final long c=0;
int d;

public static Parent madeFrom( Parent p ) {
Parent copy;
try {
copy = p.clone();
} catch( CloneNotSupportedException ex ) {
throw new AssertionError(); // can't happen
}
copy.a = 42; // init to default value again
// copy.b = 0; // Oops
return copy;
}

@Override
protected Parent clone()
throws CloneNotSupportedException
{
Parent clone = (Parent) super.clone();
// clone.c = 0; // Oops.
clone.d = 0;
return clone;
}

}
From: Marcin Rzeźnicki on
On 15 Lis, 15:58, markspace <nos...(a)nowhere.com> wrote:
> Note also that final fields can be used, they just
> can't be changed.
>

Seeing your example this sentence might seem like minor glitch which
can be passed over. But that can be easily misleading if you consider
final reference fields. Coupling shallow copy semantics with lack of
formal 'constness' leads to catastrophic results.Thus - 'clone'
considered dangerous :-)



From: Lew on
The87Boy wrote:
> I am trying to construct a superclass [instance] as itself like this:

Your question applies to all classes, not just superclasses.

> public Parent(Parent parent) {
>
> // Set this class as itself
> this = parent;
> }
>
> But it is not allowed by the compiler,

That is because 'this' always refers to the instance itself and cannot be
pointed to any other instance. Just think how confusing it'd be if 'this' was
not a pointer to "this" instance.

> but do I have to set all variables like this:
>
> public Parent(Parent parent) {
>
> // Set this class as itself
> this.id = parent.getID();
> this.cclass = parent.getCClass();

This line is confusing. I assume you're referring to an instance member of
'Parent' called 'cclass' of type 'CClass', a singularly unfortunate choice of
type name. By convention (*not* by language requirement) you capitalize the
first letter of class names but not of variable names, which you've done, but
instances named after the class should retain the rest of the camel-case
capitalization where feasible: 'cClass'.

Given the existence of the confusingly similarly-named 'class' literal and the
instance method 'getClass()', and the usual uselessness of naming something
with 'Class' as part of the class name, you should pick a more meaningful,
less confusing name than 'cClass' or 'getCClass()'.

Theoretically the variable and corresponding 'get' method for "ID" should be
either 'id'/'getId()' or 'iD'/'getID()', but people actually do make the
exception 'ID'/'getID()' or better, as you've done, 'id'/'getID()'. The
convention is a bit looser for concepts normally expressed in all caps, like
"ID", "UPC", "URL", "ISBN" or "SSN".

> }
>
> Or are there any easier way?

There are other ways, not really easier ones. From your example it looks like
you want to copy member values from the "other" object, referenced by the
'parent' pointer, to the "this" object, referenced by the 'this' pointer. As
others have said, simply copying pointers as you showed is normal, but
overriding 'clone()' is something to do judiciously [Bloch]. There are a
number of things to watch out for, like the necessity to implement 'Cloneable'.

The possible need to copy deeply is shared by the solutions. Non-primitive
member variables are references, i.e., pointers to objects. Copying a
reference yields two pointers to the same object, so changes made through one
affect the other.

Read the Javadocs
<http://java.sun.com/javase/6/docs/api/java/lang/Object.html#clone()>
<http://java.sun.com/javase/6/docs/api/java/lang/Cloneable.html>

and the relevant chapter of Bloch's /Effective Java (2nd Edition)/, Sun, 2008.
(ISBN-13: 978-0-321-35668-0, ISBN-10: 0-321-35668-3)
<http://java.sun.com/docs/books/effective/>
"Item 11: Override clone judiciously"

--
Lew