Another question about inheritance (up-casting and down-casting)

K

kevin

Hi all:

Sorry to bother you again:)

Still the question about inheritance,please see this codes below
first:

// codes start
class base{//a base class

// constructor
public base(){
System.out.println("base class construct");
}
// perform
public void perform(){
System.out.println("base class perform");
}
// destructor
public void finalize(){
System.out.println("base class destruct");
}
}


class subbase extends base{// derive from base

// constructor
public subbase(){
System.out.println("sub class construct");
}
// perform
public void perform(){
System.out.println("sub class perform");
}
// destructor
public void finalize(){
System.out.println("sub class destruct");
}
}

public class casting{// test casting class
// constructor
public casting(){
System.out.println("begin casting test");
}

public static void main(String args[]){
base father = new base();
subbase son = new subbase();

father.perform();
son.perform();

father = (base)son; // <1>
father.perform();

son = (subbase)father; // <2>
son.perform();

father = (base)((subbase)father); // <3>
father.perform();
}
}

// codes end

***************************************************
and the execution result is:
// begin
base class construct
base class construct
sub class construct
base class perform
sub class perform
sub class perform // <a>
sub class perform // <b>
sub class perform // <c>
// end

****************************************************

My question is: there are 3 castings in the codes(e.g. <1><2><3>),but
why they perform not as I like, I cast the subclass son to base class
at <1>, but at <a>,father.perform() don't print "base class perform",
the situation is similar in <2><a> and <3><c>,so, why?


****************************************************
And I am confused about how "casting" behave?
for example:

base class: sub class derive from base
+---------------+ +------------------------------+
| int nbase | | int nbase int nsub |
----------------- --------------------------------
| void fbase() | | void fbase() void fsub() |
+---------------+ +------------------------------+

so, if I declare:

base a = new base(); // a should contains nbase and fbase()
sub b = new sub(); // b should contains nbase,nsub and
fbase(),fsub()
base c;
sub d;

c = (base)b; // ? what c contains ? like a or like b
// that is to say if son class upcasting to father
class
// if the member belongs to son class should be
truncated?
d = (sub)c; // ? what d contains ? like a or like b
// that is to say if d get the members belongs to son
class
// automatically
// d == b ? i mean if equal in memory profile

*******************************************************

I am a little confused about how memory allocation changes when
upcasting
or downcasting ?



that's all

thank you!


kevin
 
H

Harish

in short: the function overriding in java is always virtual.

so even if you type cast a derived class object to a base class object
and then invoke a function,(which is overridden in the derived class)
it'll end up calling the derived class implementation.

hmmm.. am i doing someonelese'shomework?


kevin said:
Hi all:

Sorry to bother you again:)

Still the question about inheritance,please see this codes below
first:

// codes start
class base{//a base class

// constructor
public base(){
System.out.println("base class construct");
}
// perform
public void perform(){
System.out.println("base class perform");
}
// destructor
public void finalize(){
System.out.println("base class destruct");
}
}


class subbase extends base{// derive from base

// constructor
public subbase(){
System.out.println("sub class construct");
}
// perform
public void perform(){
System.out.println("sub class perform");
}
// destructor
public void finalize(){
System.out.println("sub class destruct");
}
}

public class casting{// test casting class
// constructor
public casting(){
System.out.println("begin casting test");
}

public static void main(String args[]){
base father = new base();
subbase son = new subbase();

father.perform();
son.perform();

father = (base)son; // <1>
father.perform();

son = (subbase)father; // <2>
son.perform();

father = (base)((subbase)father); // <3>
father.perform();
}
}

// codes end

***************************************************
and the execution result is:
// begin
base class construct
base class construct
sub class construct
base class perform
sub class perform
sub class perform // <a>
sub class perform // <b>
sub class perform // <c>
// end

****************************************************

My question is: there are 3 castings in the codes(e.g. <1><2><3>),but
why they perform not as I like, I cast the subclass son to base class
at <1>, but at <a>,father.perform() don't print "base class perform",
the situation is similar in <2><a> and <3><c>,so, why?


****************************************************
And I am confused about how "casting" behave?
for example:

base class: sub class derive from base
+---------------+ +------------------------------+
| int nbase | | int nbase int nsub |
----------------- --------------------------------
| void fbase() | | void fbase() void fsub() |
+---------------+ +------------------------------+

so, if I declare:

base a = new base(); // a should contains nbase and fbase()
sub b = new sub(); // b should contains nbase,nsub and
fbase(),fsub()
base c;
sub d;

c = (base)b; // ? what c contains ? like a or like b
// that is to say if son class upcasting to father
class
// if the member belongs to son class should be
truncated?
d = (sub)c; // ? what d contains ? like a or like b
// that is to say if d get the members belongs to son
class
// automatically
// d == b ? i mean if equal in memory profile

*******************************************************

I am a little confused about how memory allocation changes when
upcasting
or downcasting ?



that's all

thank you!


kevin
 
V

Virgil Green

kevin said:
Hi all:

Sorry to bother you again:)

Still the question about inheritance,please see this codes below
first:

// codes start
class base{//a base class

// constructor
public base(){
System.out.println("base class construct");
}
// perform
public void perform(){
System.out.println("base class perform");
}
// destructor
public void finalize(){
System.out.println("base class destruct");
}
}


class subbase extends base{// derive from base

// constructor
public subbase(){
System.out.println("sub class construct");
}
// perform
public void perform(){
System.out.println("sub class perform");
}
// destructor
public void finalize(){
System.out.println("sub class destruct");
}
}

public class casting{// test casting class
// constructor
public casting(){
System.out.println("begin casting test");
}

public static void main(String args[]){
base father = new base();
subbase son = new subbase();

father.perform();
son.perform();

father = (base)son; // <1>
father.perform();

son = (subbase)father; // <2>
son.perform();

father = (base)((subbase)father); // <3>
father.perform();
}
}

// codes end

***************************************************
and the execution result is:
// begin
base class construct
base class construct
sub class construct
base class perform
sub class perform
sub class perform // <a>
sub class perform // <b>
sub class perform // <c>
// end

****************************************************

My question is: there are 3 castings in the codes(e.g. <1><2><3>),but
why they perform not as I like, I cast the subclass son to base class
at <1>, but at <a>,father.perform() don't print "base class perform",
the situation is similar in <2><a> and <3><c>,so, why?

Casting doesn't change the nature of the object being referenced. It only
changes the way you reference it. Any overridden method will continue to be
overridden, even if you access it through a reference whose type is a parent
of the actual object.
****************************************************
And I am confused about how "casting" behave?
for example:

base class: sub class derive from base
+---------------+ +------------------------------+
----------------- --------------------------------
+---------------+ +------------------------------+

so, if I declare:

base a = new base(); // a should contains nbase and fbase()
sub b = new sub(); // b should contains nbase,nsub and
fbase(),fsub()
base c;
sub d;

c = (base)b; // ? what c contains ? like a or like b
// that is to say if son class upcasting to father
class

c contains a reference to the object that was created when you did "new
sub()". The nature of the object didn't change in any way because you upcast
it to a variable whose object type is a parent of the actual object.
// if the member belongs to son class should be
truncated?
d = (sub)c; // ? what d contains ? like a or like b
// that is to say if d get the members belongs to son
class
// automatically
// d == b ? i mean if equal in memory profile

Nothing is removed from an object just because you upcast a reference to it.
You are just limited (perhaps, assuming new methods are defined in the
subclass) in how you can work with the object via the new reference. You
could, for example, downcast it again and still have all the access you
originally had via the 'sub' type reference.
*******************************************************

I am a little confused about how memory allocation changes when
upcasting
or downcasting ?

It doesn't. Objects are objects. References are references. Non-primitive
variables are references to objects. Assigning to a different, compatible
variable doesn't change the object in any way.
 
A

Andrew McDonagh

kevin said:
Hi all:

Sorry to bother you again:)

Not a problem, its what this NG is for.
Still the question about inheritance,please see this codes below
first:

// codes start
class base{//a base class

// constructor
public base(){
System.out.println("base class construct");
}
// perform
public void perform(){
System.out.println("base class perform");
}
// destructor
public void finalize(){
System.out.println("base class destruct");
}
}


class subbase extends base{// derive from base

// constructor
public subbase(){
System.out.println("sub class construct");
}
// perform
public void perform(){
System.out.println("sub class perform");
}
// destructor
public void finalize(){
System.out.println("sub class destruct");
}
}

minor point Java does not have destructors - finalizers are not the
same. When the Garbage collector kicks in to free memory it may call an
objects finalizer(), but there's no guarantee that it will under certain
conditions.
public class casting{// test casting class
// constructor
public casting(){
System.out.println("begin casting test");
}

public static void main(String args[]){
base father = new base();
subbase son = new subbase();

father.perform();
son.perform();

father = (base)son; // <1>
father.perform();

all that has occurred here is that you have over made the 'father'
reference point to the son object. You can do this, because the 'son'
object is a kindOf 'base' class. Its worth noting that the explicit cast
you have done here, is not actually needed and could be removed without
effecting the outcome.

When you call father.perform(); you are still calling the 'subbase'
class method of the object that 'father' now points too.

this is because in Java all methods are virtual by default. Therefore it
does not matter that the method exists on the base class and the subbase
class, its the subbase.perform() method that will be called.

This is what polymorphic means.

Also note, that unless subbase.perform() explicitly calls:
super.perform(); then whatever the base.perform() method does, will not
happen.

i.e.

// perform
public void perform(){
super.perform();
System.out.println("sub class perform");
}


Note, that now both the 'son' and 'father' references point to the
subbase object.

The object that 'father' use to point too, is now no longer available to
the code and so may at sometime be garbage collected.

son = (subbase)father; // <2>
son.perform();

Now that the 'son' and 'father' references point to the subbase object,
the code above is really doing the same as the previous perform(), just
via a different Type of reference.
father = (base)((subbase)father); // <3>
father.perform();
}
}

// codes end

***************************************************
and the execution result is:
// begin
base class construct
base class construct
sub class construct
base class perform
sub class perform
sub class perform // <a>
sub class perform // <b>
sub class perform // <c>
// end

****************************************************

My question is: there are 3 castings in the codes(e.g. <1><2><3>),but
why they perform not as I like, I cast the subclass son to base class
at <1>, but at <a>,father.perform() don't print "base class perform",
the situation is similar in <2><a> and <3><c>,so, why?

The beauty of polymorphic behavior is that it does not matter what type
of reference you have to an object, when you call its polymorphic
method, the most derived class method will be called first.

This allows you to derive a new class from a base, ond optionally
override the base class behavior if you want too or not.

If you do, then your overridden method will be called rather than the
base class one.
****************************************************
And I am confused about how "casting" behave?
for example:

base class: sub class derive from base
+---------------+ +------------------------------+
| int nbase | | int nbase int nsub |
----------------- --------------------------------
| void fbase() | | void fbase() void fsub() |
+---------------+ +------------------------------+

so, if I declare:

base a = new base(); // a should contains nbase and fbase()
sub b = new sub(); // b should contains nbase,nsub and
fbase(),fsub()
base c;
sub d;

c = (base)b; // ? what c contains ? like a or like b
// that is to say if son class upcasting to father

As above, the up cast is unnecessary. as all that is happening is that
the base class typed reference 'c' is now pointing to an object which is
a kindOf 'base'. Whether it is a base, or any derived class of base is
irrelevant.

It does mean however that from the 'c' reference you can only treat the
'b' object as if it was a base class.
class
// if the member belongs to son class should be
truncated?
d = (sub)c; // ? what d contains ? like a or like b
// that is to say if d get the members belongs to son
class
// automatically
// d == b ? i mean if equal in memory profile

*******************************************************

I am a little confused about how memory allocation changes when
upcasting
or downcasting ?

There are no real memory changes when casting. What happens is that the
references that pointed to one object, now point to another, thats all.
that's all

thank you!

no problem.
 
J

Jeff

Part of your problem in understanding what's going to happen is,
I think, the way you have re-used and re-assigned the variables
in your main() method.

See comments in code below...
Hi all:

Sorry to bother you again:)

Still the question about inheritance,please see this codes below
first:

// codes start
class base{//a base class

// constructor
public base(){
System.out.println("base class construct");
}
// perform
public void perform(){
System.out.println("base class perform");
}
// destructor
public void finalize(){
System.out.println("base class destruct");
}
}


class subbase extends base{// derive from base

// constructor
public subbase(){
System.out.println("sub class construct");
}
// perform
public void perform(){
System.out.println("sub class perform");
}
// destructor
public void finalize(){
System.out.println("sub class destruct");
}
}

public class casting{// test casting class
// constructor
public casting(){
System.out.println("begin casting test");
}

public static void main(String args[]){
base father = new base();
subbase son = new subbase();

father.perform();
son.perform();

So far, so good. Everything as expected, right?
father = (base)son; // <1>
father.perform();

Now father refers to a subbase (specifically, the same object
that was originally assigned to the variable son earlier)
son = (subbase)father; // <2>
son.perform();

Here's where you get into trouble. In <1> above, father is
already referring to the original value of son, so this action
actually DOES NOT CHANGE what son refers to. son still refers to
a subbase object.
father = (base)((subbase)father); // <3>
father.perform();

Again, father still refers to the original subbase (son) object
from the assignment in <1>


I hope this helps. Try another sample program, but don't re-use
your variables. Create new ones for each behavior you are trying
to demonstrate.
 
E

Eric Sosman

kevin said:
Hi all:

Sorry to bother you again:)

For future reference, comp.lang.java.help is a newsgroup
more suited to "elementary" questions like this.
Still the question about inheritance,please see this codes below
first:
[... code snipped; see up-thread ...]

My question is: there are 3 castings in the codes(e.g. <1><2><3>),but
why they perform not as I like, I cast the subclass son to base class
at <1>, but at <a>,father.perform() don't print "base class perform",
the situation is similar in <2><a> and <3><c>,so, why?

Here's a discipline that may help you understand what's
going on: Remember always that the variables like `father'
and `son' are not objects, but references to objects. You
do not call a method of `father' or of `son', but a method
of the object `father' or `son' refers to. Using a cast to
change the type of the reference value does not affect the
nature of the target object: no matter which reference you
use for the method call, the object itself provides the
method's implementation.

If you think about it a bit, you'll realize that this
is the "right" way for things to work. Suppose you have a
collection called `zoo' full of various Animal objects.
Actually, none of them is an Animal; they're all subclasses
of Animal: Gorilla extends Animal, Titmouse extends Animal,
TasmanianDevil extends Animal, and so on. Every Animal
implements an eat() method, so the code for feeding time
at the zoo looks like

for (Iterator it = zoo.iterator(); it.hasNext(); ) {
Animal inmate = (Animal)it.next();
inmate.eat();
}

Now, if the first Animal is an Octopus, the first inmate.eat()
call should invoke Octopus' eat() method. And if the second
is a Cobra, the second inmate.eat() call should invoke Cobra's
eat() method, and so on. I put it to you that this is the way
you want method invocation to work: if the Animal-ness of the
`inmate' reference controlled which method implementation is
called, how would you feed the Anaconda and the Armadillo?
And I am confused about how "casting" behave?
for example:

base class: sub class derive from base
+---------------+ +------------------------------+
| int nbase | | int nbase int nsub |
----------------- --------------------------------
| void fbase() | | void fbase() void fsub() |
+---------------+ +------------------------------+

so, if I declare:

base a = new base(); // a should contains nbase and fbase()

`a' refers to an object of the class `base'. This object
has an `nbase' field and implements an `fbase' method.
sub b = new sub(); // b should contains nbase,nsub and
fbase(),fsub()

`b' refers to an object of the class `sub'. This object
has `nbase' and `nsub' fields, and implements `fbase' and
`fsub' methods. (It's not clear from your diagram whether
the `sub' object inherits `nbase' and `fbase', or whether
it overrides them -- using "overrides" loosely with `nbase').
base c;
sub d;

c = (base)b; // ? what c contains ? like a or like b
// that is to say if son class upcasting to father
class

`c' refers to the same `sub' object that `b' does. The
only difference is that the compiler will not allow you to
write `c.nsub' or `c.fsub()', because `c' is also capable of
referring to a `base' object that lacks these members. Note
that the `sub' object itself is unchanged. (By the way, the
cast is unnecessary: every `sub' is a `base', so you can use
a `sub' reference anywhere you can use a `base' reference.
Every Hummingbird is an Animal, so Animal x = new Hummingbird()
is perfectly all right and requires no cast.)
// if the member belongs to son class should be
truncated?
d = (sub)c; // ? what d contains ? like a or like b
// that is to say if d get the members belongs to son
class
// automatically

`d' refers to the same `sub' object that `b' and `c' do.
The cast is required here, because `c' is capable of referring
to a plain `base' object that is not a `sub'. Every Hummingbird
is an Animal, but not all Animals are Hummingbirds.
// d == b ? i mean if equal in memory profile

`d == b' is true: Both reference variables refer to the
same object.
I am a little confused about how memory allocation changes when
upcasting
or downcasting ?

It does not change at all: The target object is not affected
by (is not even aware of) the type of the variable that refers
to it.
 
R

Ryan Stewart

kevin said:
Hi all:

Sorry to bother you again:)

Still the question about inheritance,please see this codes below
first:
[...]
I'm sure you got plenty of good advice from everyone here. I'm afraid I didn't
take the time to read everything. I am just going to interject that based on
your questions, you appear to trying to learn Java by trial and error. Try
working through some basic Java tutorials or a good book. People here tend to be
very patient with beginners who are truly trying to learn, but that patience is
not without limit. Try this for starters:
http://java.sun.com/docs/books/tutorial/

Here is the index to Sun's tutorials:
http://java.sun.com/docs/books/tutorial/reallybigindex.html

And this should clear up your inheritance questions if the eloquent responses
you've recieved have not already done so:
http://java.sun.com/docs/books/tutorial/java/javaOO/index.html

In addition, a simple Google search for "java tutorial" will bring up tons of
good (and not so good, of course) sites.
 
R

Ryan Stewart

Andrew McDonagh said:
minor point Java does not have destructors - finalizers are not the same. When
the Garbage collector kicks in to free memory it may call an objects
finalizer(), but there's no guarantee that it will under certain conditions.
To clarify, an object's finalizer will be called before the object's storage is
reused, but that may never be necessary.
There are no real memory changes when casting. What happens is that the
references that pointed to one object, now point to another, thats all.
No. Casting causes the reference type to be different. It still points at the
same object.
 
A

Andrew McDonagh

Ryan said:
To clarify, an object's finalizer will be called before the object's storage is
reused, but that may never be necessary.



No. Casting causes the reference type to be different. It still points at the
same object.

I think we are both saying the same thing, but from different angles.

in the case of

Integer i = new Integer(1);

// We could have done ...

Object o = (Object)i;

//which is a legal but unnecessary upcast.

// Then followed by...

Integer anotherI = (Integer)o;

And so I agree, with completely with your statement.

However, in the OPs code we had the following situation

Integer i1 = new Integer(1);
Integer i2 = new Integer(2);

Object o1 = (Object)i1;

o1 = (Object)i2;

So, in this situation, the o1 reference is now pointing to a different
object.
 
R

Ryan Stewart

[...]
However, in the OPs code we had the following situation

Integer i1 = new Integer(1);
Integer i2 = new Integer(2);

Object o1 = (Object)i1;

o1 = (Object)i2;

So, in this situation, the o1 reference is now pointing to a different object.

Ah, I see. I should have read closer. It seemed you were making a blanket
statement.
 
A

Andrew McDonagh

Ryan said:
[...]
However, in the OPs code we had the following situation

Integer i1 = new Integer(1);
Integer i2 = new Integer(2);

Object o1 = (Object)i1;

o1 = (Object)i2;

So, in this situation, the o1 reference is now pointing to a different object.


Ah, I see. I should have read closer. It seemed you were making a blanket
statement.

Thats ok :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top