• Post Reply Bookmark Topic Watch Topic
  • New Topic

Casting and sub-classes  RSS feed

 
Urs Waefler
Ranch Hand
Posts: 192
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is the code: I do not understand the casting (B). o1 is an object of C, the type of the reference is A. C is a B. I do not understand the casting properly. Please help.
 
Junilu Lacar
Sheriff
Posts: 11493
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You might understand it better if you use proper names and not just meaningless ones like A, B, and C.

class Vehicle ...
class WheeledVehicle extends Vehicle
class MotorizedWheeledVehicle extends WheeledVehicle.

Now, it's clear that a MotorizedWheeledVehicle is a special kind of WheeledVehicle, right?

If you analyze the relationships, it's not that hard to see that a MotorizedWheeledVehicle is also a special kind of Vehicle.

If you substitute these names in your code, you have this:

Does that make more sense?
 
Urs Waefler
Ranch Hand
Posts: 192
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The question remains. In your code: someVehicle is a MotorizedWheeledVehicle. Why there is a cast to WheeledVehicle? If someVehicle is a Vehicle, then I understand; the cast must be because Vehicle is the superclass of WheeledVehicle. How is it?
 
Liutauras Vilda
Sheriff
Posts: 4921
334
BSD
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Urs Waefler wrote:In your code: someVehicle is a MotorizedWheeledVehicle.

Actually other way round.
 
Urs Waefler
Ranch Hand
Posts: 192
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A MotorizedWheeledVehicle is a someVehicle?
 
Liutauras Vilda
Sheriff
Posts: 4921
334
BSD
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Urs Waefler wrote:A MotorizedWheeledVehicle is a someVehicle?

Don't use reference variables to define inheritance tree as at any given point of time they can refer to somebody else.

However, in this particular case someVehicle (in Junilu's exmaple) represents Vehicle. So let's call it Vehicle.

MotorizedWheeledVehicle IS-A Vehicle, but not necessarily that is true other way round. Not every Vehicle IS-A MotorizedWheeled...
 
Urs Waefler
Ranch Hand
Posts: 192
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In my intitial code you can see: o1 is a C, C is the sublass of B. Thus there is no need for a casting, but a casting is needed here. Why? If I change from A to C, then the casting is not needed. The following code works fine: It has something to do with the reference type. How does it work?
 
Liutauras Vilda
Sheriff
Posts: 4921
334
BSD
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Urs Waefler wrote:In my intitial code you can see:

o1 is a C

No. Referene variable is of type A. Second time mentioning that idea.

Urs Waefler wrote:Thus there is no need for a casting, but a casting is needed here.

Sounds contradicting, not sure what you mean.
 
Urs Waefler
Ranch Hand
Posts: 192
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In this case: C is a B and B is an A. I do not understand the casting; you can save everthing in A, because A is the superclass. There is no need for a casting at all; but without the casting it does not compile.
 
Liutauras Vilda
Sheriff
Posts: 4921
334
BSD
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think the confusion arise when you think about the superclass as about the descendant (like super does everything), but that is not true. There is another name for that - base class.

The class which extendends something, does more than its super class, the one which is being extended (let's try this way and sorry for used might not right terminology, but we need simpler examples here).

Think that super class is the worst one. Everything what extends it, it gets better.

B extends A

So, A does only 'a'
B does 'b' and 'a', because it inherits from A 'a', so it is better than its super (base class) class in that sense. I think super class is misleading name a bit.

Now. Think in simple words, that if you ever get something, you are agreed by default to get what is better only, otherwise you require a confirmation: "ok, you didn't gave me everything, but let's suppose you did).

so, when you have
A = new B()

We know that A can do only a, and B can do a and b, which is better, hence A = new B() is allowed. (ignore non valid syntax)

Now we know already, that B does a and b, and A only a, so:
B = new A() is not allowed, unless you say, OK, lets assume you gave me better, which is a cast:
B = (B) new A();

That let's compile, but won't let run, but that is different topic.

I made it quite messy probably, but might it will help you understand that way.
 
Junilu Lacar
Sheriff
Posts: 11493
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I suspect that the problem lies with OP misunderstand what casting does. A cast DOES NOT change the type of an object.  It simply tells the compiler to consider a reference variable as assignment-compatible with another reference variable.  A cast is required if you are trying to assign a more general reference variable to a more specific variable, as is the case when you try to assign a Vehicle reference to a WheeledVehicle reference, or since you seem to prefer the more confusing and abstract A, B, C names, when you try to assign an A reference to a B reference variable.

The object's runtime type NEVER changes from Vehicle to WheeledVehicle just because you used a cast. The actual runtime type is still MotorizedWheeledVehicle, the class that was used to instantiate the object.

A cast is needed only when you are assigning from a more general reference type to a more specific reference type.  A cast is not needed when you are assigning a more specific reference type to a more general reference type.

So the rules for casting is pretty much the same for narrowing/widening conversions. You don't need a cast for widening conversions but you DO need a cast for narrowing conversions.  A subclass is a specialization of its superclasses or in other words, a subclass is a narrower type of its superclasses.
 
Urs Waefler
Ranch Hand
Posts: 192
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think you are right wirth the terminology; maybe superclass is confusing. Base class is a better term. But what is about this code: It compiles, I fully understand it; B is the base class. Let us have a look again at this code: Consider this line: What is the base class of o1? I think it is C. There is a casting. That means, the functionalities are limeted to the ones of B. Thus o2.i = 20.

If I try to compile it without the casting, I get the following message:

TestClass.java:4: error: incompatible types: A cannot be converted to B
      B o2 = o1;

It seems that o1 is not a C but an A. How do you explain that?
 
Liutauras Vilda
Sheriff
Posts: 4921
334
BSD
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Urs, you have mentioned you have Jeanne's and Scott's book and you liked it a lot.

Have you tried to read the chapter about that?
I think it is safe to say that in a book all is explained way better than I could here, because it was reviewed hundreds of times, technical reviews were done, some other reviews were done probably - book is a high standard book, so you should try to read carefully, probably read 10-20-30, if needed 40 times and try to understand.

Seems that we kinda repeating ourselves here what has been explained already elsewhere.

I'm not saying don't ask questions because we won't answer - I'm just trying to help you to go through all that tough experience slightly easier.
 
Urs Waefler
Ranch Hand
Posts: 192
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think, now I got it, thanks Junilu Lacar. o1 is a C, but its reference is an A. We must differentiate between the objects and the references.
 
Junilu Lacar
Sheriff
Posts: 11493
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Perhaps it will be helpful to expand the example with a few more subclasses:


Given all the class definitions above, you have this:
 
Henry Wong
author
Sheriff
Posts: 23295
125
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Urs Waefler wrote:I think, now I got it, thanks Junilu Lacar. o1 is a C, but its reference is an A. We must differentiate between the objects and the references.


Another point to make is the compiler runs during compile time -- and not runtime. Kinda obvious really. And based on the specification, there is nothing defined that is good enough to determine the type of the object (guaranteed), without actually running the application. Hence, the compiler uses the reference type to determine a possible types.

Henry
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!