• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Understanding creating a "super" class obj from a "subclass" object

 
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi all. I'm new to Java, but have been programming in procedural languages in IBM midrange systems for years. I'm trying to get this object oriented programming theory into my head. I've been going through the Sun/Oracle Java Tutorials. The part that talks about "inheritance" is where I'm confused (at least today). They show examples of creating a "Bicycle" class and a couple of subclasses called MountainBike and RoadBike. Then they do this:

public class TestBikes {
public static void main(String[] args){
Bicycle bike01, bike02, bike03;

bike01 = new Bicycle(20, 10, 1);
bike02 = new MountainBike(20, 10, 5, "Dual");
bike03 = new RoadBike(40, 20, 8, 23);

bike01.printDescription();
bike02.printDescription();
bike03.printDescription();
}
}

The following is the output from the test program:
Bike is in gear 1 with a cadence of 20 and travelling at a speed of 10.

Bike is in gear 5 with a cadence of 20 and travelling at a speed of 10.
The MountainBike has a Dual suspension.

Bike is in gear 8 with a cadence of 40 and travelling at a speed of 20.
The RoadBike has 23 MM tires.

----------
What I don't follow or understand is: if the bike01, bike02 & bike03 objects are created from the Bicycle class, then MountainBike & RoadBike objects are assigned to them, doesn't the Bicycle class drop the extra fields/variables and methods that were added in the subclasses? I seems to me that a square peg is being driven into a round hole. How can the subclasses be "cast" to the super class and not "drop off" or otherwise lose the fields and methods that make them different from the super class.

Thank you in advance for taking the time to look at this post, and for any replies that you make.
 
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Here is a visual representation that maybe will clear things up:

(Bicycle ((MountainBike)(RoadBike)(Any other subclass))

So what this is trying to convey is that MountianBike and RoadBike are subsets of Bicycle. Everything that Bicycle has will be in both MountianBike as well as RoadBike. But on another note MountianBike and RoadBike may have different components (both variables and methods) inside of them that are only available to them. Its the same thinking as there are many birds(Bicycle class), but different birds have different traits and functions. There are birds that can fly like a robin and there are birds that cannot fly penguin.

So, bike01 comes only with the methods and variables that are defined in the Bicycle class.
bike02 comes with the methods and variable that are available to the MountianBike class as well as the Bicycle class.
And bike03 comes with the methods and variable that are available to the MountianBike class as well as the Bicycle class.

Everything would be inherited from the super class, not dropped off.
 
lowercase baba
Posts: 13089
67
Chrome Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
something to remember...

"bike01", "bike02", and "bike03" are REFERENCES, not actual objects. I think of them as index cards with a street address written on them. They are only allowed to hold the address of a certain type of thing. Since we declared them as "Bicycle" references, they can hold the address of a Bicycle...but they can hold the address of ANY kind of Bicycle.

So...when you have this:



You create three objects, one is a Bicycle, one is a MountainBike (a kind of Bicycle), and one is a RoadBike (also a kind of Bicycle). The reference is valid. You would not be able to create a Dog object and use a Bicycle reference, since a Dog is NOT a Bicycle.

Your references (bike01, bike02 and bike03) only know about methods defined in the Bicycle class. So you could not use bike02 to call a method only defined in the MountainBike class.

However, MountainBike and RoadBike override the printDecsription method. That means that even though Bicycle has the printDescription method defined and written out, the other classes ALSO have the method defined. So when you call bike02.printDescription(), it uses what is written in the MountainBike class, and the same with bike03 and the RoadBike.
 
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
… and welcome to the Ranch (after 3½ years!)
 
Thomas A Davis
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you, Campbell, Fred & Avery. Yes, it's been 3 1/2 years since I registered here. Always hate to ask questions seems like, but after reading and reading, I couldn't resolve that idea in my head.

Fred, your response begins to make the most sense to me, where you said ".but they can hold the address of ANY kind of Bicycle. " I'll need to play with that idea and see how it works, so I will learn it. In the back of my head, it still seems that the Bicycle class only has x variables and methods declared. MountainBike and RoadBike have inherited those x variables and added y variables & methods. It would then appear that the Bicycle class object would have no "room" for the y (additional variables) that both the other subclasses had. In that case, bike02 and bike03 would lose the additional fields and methods that they were created with.

I can easily see where a "Bicycle" class object could be cast into a subclass object of either MountainBike or RoadBike because they have all the fields of "Bicycle", plus some. Going the other way, from more fields into something with less fields would drop or lose fields. (Fields = variables... my RPG language coming through.)

So, Fred, if I understand what you said, that ANY subclass object can be cast into the super class type without losing any information? Is this correct? Thank you, Tom
 
Ranch Hand
Posts: 62
Netbeans IDE MySQL Database Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Thomas A Davis wrote:So, Fred, if I understand what you said, that ANY subclass object can be cast into the super class type without losing any information? Is this correct? Thank you, Tom



I had loads of trouble with this coming from scripting languages. Like Fred said the key is that casting affects the object reference not the object itself.

The metaphor/analogy which always spoke to me was from Head First Java - (I would suggest the book strongly to someone coming from a procedural background) this isn't what they use in the book but this is how it is in my mind now when I think of casting/polymorphism:

Say you have a class StandardTV which has five channels and five methods selectChannel_1 - selectChannel_5 (bad OO design notwithstanding ).

I can say StandardTV myStdTVref = new StandardTV()

On the right of the = I create a StandardTV object. On the left of the = I create a StandardTV reference.

myStdTVref is like a remote control for a StandardTV, it tells me I have my five badly designed methods which I can use to pick channels 1-5.

Now I extend StandardTV to SuperTV with 140 channels and using my appalling OO design I give SuperTV 140 methods selectChannel_1 - selectChannel_140.

Now I could say SuperTV mySupTVref = new SuperTV()

mySupTVref is a remote with the 140 channels to pick from.

But I could also say StandardTV mySupTVref = new SuperTV()

Now, I created (on the right of the =) a SuperTV but I only pointed (on the left of the =) a StandardTV reference at it so my remote only has the 1-5 channel methods on it. These work fine because my SuperTV has those five channels, it just happens to have (extend) 135 more which I can't access at the moment. But the important thing is that just because the remote doesn't show the channels (methods) doesn't mean the TV doesn't have them. Later on I can cast mySupTVref back to a SuperTV reference and I can then access all those 140 channels*. The SuperTV object never changed - I just took away and added buttons to the remote.

*Take care casting down to the subtype because if there is more than one subtype casting to the wrong one will stitch you - when you get here look at instanceof to check what the object really is.

I don't know if this will help you but it is the way I managed to get it into my head. When you get it you'll see that it is just a duplicate of what Fred said really, just a different example.
 
Thomas A Davis
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Wow, this is getting scary. I think I'm actually beginning to understand that! Thanks Phil. That really helped. I won't say that I'm confident about trying to explain it to someone else, but it's starting to make sense. Thank you very much to all who responded. This site is much better than I anticipated. I'll try to locate a copy of Head First Java. Thanks for the book tip. Everyone has been so very helpful. Have a great day(evening). Tom
 
fred rosenberger
lowercase baba
Posts: 13089
67
Chrome Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
note that in your example code above, there isn't any casting. A MountainBike IS-A Bicycle.

They always talk about a hierarchy - parent and child classes (or super and sub-classes). In some ways, a Venn Diagram makes more sense. you have your pool/circle of Bicycles. Completely enclosed in that is a smaller circle of MountainBikes, and a separate but still enclosed circle of RoadBikes.

a Bicycle reference can point to ANYTHING inside the Bicycle circle - which all MountainBike and RoadBikes are.

A Bicycle reference can NOT point to (say) a Dog object.

In your example, the compiler knows exactly what each object is, and knows what is valid to point to and what is not.

Casting comes into play when the compiler cannot know the actual object type. You may have (poorly written) code like this:

In this code, myObject could point to ANYTHING, since all objects derive (directly or indirectly) from the Object class, so this is valid. But you as a programmer know that you bought your child a MountainBike, and that getChristmasPresent() will return that. You want to be able to call the methods in MountainBike, so you can instead cast what is returned, replacing the above with this:

without the cast (the "(MountainBike)"), the compiler would say "You can't do this....getChristmasPresent returns an Object, and a MountainBike reference can't point to that!!!". Since you KNOW the object will be a MountainBike, putting in that cast says to the compiler "Hey, I know it doesn't LOOK like this should work, but I know what I'm doing and it is OK."

The compiler will go ahead and compile and give you an executable.

BUT....

Let's say your wife decides to return the MountainBike, and instead gets a puppy for the present. When the code runs, getChristmasPresent will return a puppy. The JVM then sees you saying "Let me control this Puppy object with a MountainBike reference", and says "Heck no!!! I'm shutting you down!!!" and throws an exception.

Casting does NOT change the actual object. It simply says "things look bad, but this will work, I promise". If so, great. If not, you get an exception thrown at runtime.
 
Campbell Ritchie
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Thomas A Davis wrote:. . . Always hate to ask questions seems like, . . .

I hope you haven’t been struggling for 3½ years . We want people to ask questions, if only because you get interesting answers.
 
Thomas A Davis
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Fred,

After re-reading your post (in the light of day) it makes even more sense. Especially when you said "Your references (bike01, bike02 and bike03) only know about methods defined in the Bicycle class. So you could not use bike02 to call a method only defined in the MountainBike class." I think I see what you're talking about.

Then "However, MountainBike and RoadBike override the printDecsription method. That means that even though Bicycle has the printDescription method defined and written out, the other classes ALSO have the method defined. So when you call bike02.printDescription(), it uses what is written in the MountainBike class, and the same with bike03 and the RoadBike." This I see, how those could (and did) print the descriptions that they did. Fantastic!

Yes I see now. Okay, maybe one last question... In what situation would I want to do something like that? Of course, I'm not a "java programmer" (yet), so I have no idea why that would be useful. However, I do understand now what you're saying and how it works. Thank you much for the help.

And Campbell, yes, on and off for 3 1/2 years I've been trying to learn this stuff. I had my "day job" that would sometimes require many programming hours and I would have to drop my Java education. By the time I got back to it, I had forgotten some and wanted to re-read to catch up. Anyway, my old programming environment is going away soon and we now are using a new system written in Java with an Oracle database. Looks like I'll have more time (hopefully) to devote to finally learning and becoming proficient at Java.

I'd again like to thank you, one and all, for you kind help. I expect I'll be back again, BEFORE another 3 1/2 years go by.
 
fred rosenberger
lowercase baba
Posts: 13089
67
Chrome Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well again...GENERALLY speaking...

Let's say I own a bike shop. I have a BikeShop class that has a collection of Bikes - my inventory. Perhaps I want to look at each and every Bike I own, and if it's been in stock for over a year, I want to discount the price.

A collection can only hold one type of thing - you have to tell the compiler what it will hold. So, I could have one collection that ONLY holds MountainBikes. Another collection that ONLY holds RoadBikes. Another that ONLY holds KidBikes....Each time I start carrying a new kind of bike, I would need to go back into my code that manages my inventory, add a new collection for that new type, then write a bunch of new code to process those types...

ugh...what a mess.

Instead, I can define a collection that holds Bikes. Due to the joys of polymophism, I can put in ANYTHING that is a bike. All of the above types, plus, maybe next year I start carrying RecumbantBikes. As long as it is a Bike, it can go into my Inventory without touching a line of code. THAT is pretty cool. My code that iterates through my inventory DOES NOT CARE, as long as it is a Bike.

This sort of behavior is even more prevalent once you start using interfaces. An interface simply defines what methods the class must implement. ANY type can be returned, as long as it implements the interface. So in a year or three, a completely different object type can be returned, but the receiving code still works.

Remember that in the "real world", you will have teams of people writing software. In fact, sometimes the software is written by a different company (i.e. third party software) and you are simply using it. You have NO control over what they do. So you want your code to be as flexible as possible. You may not care what the 'real' object type is, as long as you can call the five or so methods you need to call on it. That is what interfaces and polymorphism give you.
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic