Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.java.programmer > #8748 > unrolled thread
| Started by | Chad <cdalten@gmail.com> |
|---|---|
| First post | 2011-10-12 18:27 -0700 |
| Last post | 2011-10-12 23:40 -0700 |
| Articles | 6 — 5 participants |
Back to article view | Back to comp.lang.java.programmer
Java casting question Chad <cdalten@gmail.com> - 2011-10-12 18:27 -0700
Re: Java casting question Arne Vajhøj <arne@vajhoej.dk> - 2011-10-12 21:36 -0400
Re: Java casting question Lew <lewbloch@gmail.com> - 2011-10-12 19:05 -0700
Re: Java casting question Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2011-10-13 10:24 +0000
Re: Java casting question Arne Vajhøj <arne@vajhoej.dk> - 2011-11-06 17:08 -0500
Re: Java casting question Travers Naran <tnaran@gmail.com> - 2011-10-12 23:40 -0700
| From | Chad <cdalten@gmail.com> |
|---|---|
| Date | 2011-10-12 18:27 -0700 |
| Subject | Java casting question |
| Message-ID | <c6d9d3ed-7892-40e0-ac9a-abb957b93241@e9g2000prg.googlegroups.com> |
Given the following...
class X {
void f1() { System.out.println("XXX");}
void f2() { System.out.println("AAA"); f1();}
}
class Y extends X {
void f1() { System.out.println("YYY"); }
}
class Z extends X {
void f1() { System.out.println("ZZZ"); }
}
public class Main {
static void g(X a) {
a.f2();
}
public static void main(String[] args) {
X x = new X();
Y y = new Y();
Z z = new Z();
Object obj = new Y();
((X) obj).f2();
g(z);
//y = (Y)x;
}
}
I get the following output..
AAA
YYY
AAA
ZZZ
The question is about
Object obj = new Y();
((X) obj).f2();
How come YYY, but not XXX, gets printed on the second line? Both f1()
and f2() are in class X. So shouldn't f1() also have been casted to
(type) X?
Chad
[toc] | [next] | [standalone]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2011-10-12 21:36 -0400 |
| Message-ID | <4e964097$0$281$14726298@news.sunsite.dk> |
| In reply to | #8748 |
On 10/12/2011 9:27 PM, Chad wrote:
> Given the following...
>
> class X {
> void f1() { System.out.println("XXX");}
> void f2() { System.out.println("AAA"); f1();}
> }
>
> class Y extends X {
> void f1() { System.out.println("YYY"); }
> }
>
> class Z extends X {
> void f1() { System.out.println("ZZZ"); }
> }
> public class Main {
>
> static void g(X a) {
> a.f2();
> }
> public static void main(String[] args) {
> X x = new X();
> Y y = new Y();
> Z z = new Z();
>
> Object obj = new Y();
> ((X) obj).f2();
> g(z);
> //y = (Y)x;
> }
>
> }
>
> I get the following output..
>
> AAA
> YYY
> AAA
> ZZZ
>
>
> The question is about
>
> Object obj = new Y();
> ((X) obj).f2();
>
>
> How come YYY, but not XXX, gets printed on the second line? Both f1()
> and f2() are in class X. So shouldn't f1() also have been casted to
> (type) X?
((X) obj).f2();
and
((Y) obj).f2();
should give the same output.
Virtual methods are stored in the object and it really
does not matter what type the ref is declared to.
Arne
[toc] | [prev] | [next] | [standalone]
| From | Lew <lewbloch@gmail.com> |
|---|---|
| Date | 2011-10-12 19:05 -0700 |
| Message-ID | <4447573.399.1318471540216.JavaMail.geo-discussion-forums@prfp13> |
| In reply to | #8749 |
Arne Vajhøj wrote:
> Chad wrote:
>> Given the following...
>>
>> class X {
>> void f1() { System.out.println("XXX");}
>> void f2() { System.out.println("AAA"); f1();}
>> }
>>
>> class Y extends X {
>> void f1() { System.out.println("YYY"); }
>> }
>>
>> class Z extends X {
>> void f1() { System.out.println("ZZZ"); }
>> }
>> public class Main {
>>
>> static void g(X a) {
>> a.f2();
>> }
>> public static void main(String[] args) {
>> X x = new X();
>> Y y = new Y();
>> Z z = new Z();
>>
>> Object obj = new Y();
>> ((X) obj).f2();
>> g(z);
>> //y = (Y)x;
>> }
>>
>> }
>>
>> I get the following output..
>>
>> AAA
>> YYY
>> AAA
>> ZZZ
>>
>>
>> The question is about
>>
>> Object obj = new Y();
>> ((X) obj).f2();
>>
>>
>> How come YYY, but not XXX, gets printed on the second line? Both f1()
>> and f2() are in class X. So shouldn't f1() also have been casted [sic] to
>> (type) X?
The past participle of "to cast" is "cast", not "casted".
Casting from a type to a supertype is automatic, so the '(X)' cast in your code is superfluous. Since 'Y' /is-an/ 'X',. your 'obj' of type 'Y' is already of type 'X'; no cast needed. (In Java, casting to a parent type is "upcasting" or "widening", and comes for free. Casting to an extending type is "downcasting" or "narrowing", and requires a cast operator.)
And no, you should not see the 'X' version of the output from your 'Y' instance, for the reason Arne explained:
> ((X) obj).f2();
>
> and
>
> ((Y) obj).f2();
>
> should give the same output.
>
> Virtual methods are stored in the object and it really
> does not matter what type the ref is declared to.
To put it another way, the object instance "knows" its own type. You cannot call a method on the supertype that exists only in the subtype, but if you call a method that exists in the supertype that the instance's subtype overrides, you will get the overridden version.
This is a key to how object-oriented programming works.
Instances own their own members (methods and variables); the declared type only controls what the compiler is allowed to see, not how the method behaves.
Arne referred to "virtual methods". That means the method call is dispatched to the instance, not literally called from the reference. The instance uses its own version of the method - the parent type's if not overridden, the derived type's if it is overridden.
Read the Java Language Specification (JLS) for the gory details.
--
Lew
[toc] | [prev] | [next] | [standalone]
| From | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| Date | 2011-10-13 10:24 +0000 |
| Message-ID | <slrnj9df30.6gl.avl@gamma.logic.tuwien.ac.at> |
| In reply to | #8750 |
Lew <lewbloch@gmail.com> wrote:
> To put it another way, the object instance "knows" its own type.
> You cannot call a method on the supertype that exists only in the
> subtype, but if you call a method that exists in the supertype that
> the instance's subtype overrides, you will get the overridden version.
At compile-time, the static type determines which method signature is
picked, but at runtime the actual implementation for that signature
is picked based on the object's actual type.
Here is another example:
class Test {
void f1(Test o) { System.out.println("Test.f1(Test)"); }
}
class SubTest extends Test {
void f1(Test o) { System.out.println("SubTest.f1(Test)"); }
void f1(SubTest o) { System.out.println("SubTest.f1(SubTest)"); }
}
public class Main {
public static void main(String[] args) {
SubTest st = new SubTest();
st .f1(st);
((Test) st) .f1(st);
}
}
Output:
SubTest.f1(SubTest)
SubTest.f1(Test)
This shows, how the compiler settles on a method:
for the first call, the compiler sees static type SubTest, and
from among the two over*loads* picks the one most specifically
matching the static type of the arguments: f1(SubTest).
for the second call, the compiler sees static type Test, and
Test only has one version f1(Test), so the compiler picks that.
At runtime, however, SubTest.f1(Test) is called, as the object
itself is a SubTest.
> This is a key to how object-oriented programming works.
yup
PS: (for Lew)
Lew <lewbloch@gmail.com> wrote:
>>> Object obj = new Y();
>>> ((X) obj).f2();
> Casting from a type to a supertype is automatic,
> so the '(X)' cast in your code is superfluous.
The premise did not apply, thus neither does the conclusion.
[toc] | [prev] | [next] | [standalone]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2011-11-06 17:08 -0500 |
| Message-ID | <4eb7056b$0$288$14726298@news.sunsite.dk> |
| In reply to | #8750 |
On 10/12/2011 10:05 PM, Lew wrote: > Arne Vajhøj wrote: >> ((X) obj).f2(); >> >> and >> >> ((Y) obj).f2(); >> >> should give the same output. >> >> Virtual methods are stored in the object and it really >> does not matter what type the ref is declared to. > > To put it another way, the object instance "knows" its own type. You cannot call a method on the supertype that exists only in the subtype, but if you call a method that exists in the supertype that the instance's subtype overrides, you will get the overridden version. > > This is a key to how object-oriented programming works. > > Instances own their own members (methods and variables); the declared type only controls what the compiler is allowed to see, not how the method behaves. It may be worth noting that even though in Java all (non static) methods are virtual then there are other OO languages like C++ and C# where one need to explicit declare them virtual. Arne
[toc] | [prev] | [next] | [standalone]
| From | Travers Naran <tnaran@gmail.com> |
|---|---|
| Date | 2011-10-12 23:40 -0700 |
| Message-ID | <j7614l$ehf$1@dont-email.me> |
| In reply to | #8748 |
On 12/10/2011 6:27 PM, Chad wrote: > AAA > YYY > AAA > ZZZ > > > The question is about > > Object obj = new Y(); > ((X) obj).f2(); > > > How come YYY, but not XXX, gets printed on the second line? Both f1() > and f2() are in class X. So shouldn't f1() also have been casted to > (type) X? You're not understanding what casting in Java means, nor how Java implements methods. You seem to be thinking that (X)obj _converts_ obj into an instance of X complete with X's methods. That is incorrect. Obj will _always_ remember it is Y and any method calls on Obj will go to Y's methods first. Casting can _never_ change that. Ever.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.java.programmer
csiph-web