This week's book giveaway is in the Servlets forum.
We're giving away four copies of Murach's Java Servlets and JSP and have Joel Murach on-line!
See this thread for details.
The moose likes Java in General and the fly likes Polymorphism example - where would we ever use this construct? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Polymorphism example - where would we ever use this construct?" Watch "Polymorphism example - where would we ever use this construct?" New topic
Author

Polymorphism example - where would we ever use this construct?

Billy Vandory
Ranch Hand

Joined: Mar 23, 2010
Posts: 57
..construct may not be the right word, but take this example:


Ok I understand this, and how polymorphism work. but the following line:



Why would someone ever instantiate the B with A? Is there a real world example that could used to explain where this could be used?

The only reason I could think of is it limits the scope of the methods available on 'a', but then you could just down? cast. (is it down or up? B b = (B) a;)

I have no specific reason for asking this, just a thought that entered my narrow mind. But if it's handy for some reason, maybe I can incorporate it.

Honestly, in my code, I don't find many opportunities to extend my classes, and I think thats a big indicator im not ooping correctly. I did procedural C for years and OOP
is still kinda strange to me. I'm the type of guy that writes procedural code using objects, if you get what im saying. But I am trying hard to break that habit and write good code.

Thanks

Booly.
Jim Hoglund
Ranch Hand

Joined: Jan 09, 2008
Posts: 525
Billy : Let's construct a scenario to illustrate how polymorphism is really used. Consider a
hypothetical TV remote control.

Let's say that interface BasicControl declares methods: on(), off(), volume() and channel() and
that class RemoteV1 implements this interface; nothing extra, just the declared functions. The
methods available on 'x' would be the same for either "BasicControl x = new RemoteV1()" or
"RemoteV1 x = new RemoteV1()". But since we've been told to "design to the interface", we
deploy our program with the first "interface" definition.

Now it's time for an upgrade, adding methods mute() and sleepTimer(). Let's declare the new
methods in interface BetterControl which extends BasicControl. The new implementing class will
be RemoteV2 which extends RemoteV1. Also, let's say that an improved channel() method has
been developed and will be included in RemoteV2.

So what do we have? In writing RemoteV2 we didn't disturb the validated RemoteV1 methods
as they were inherited. The new mute() and sleepTimer() methods were coded and validated.
We decided, however, to include an overriding channel() method with better performance.

Older remotes can be upgraded by replacing RemoteV1 references with RemoteV2 and no other
changes. This works because "BasicControl x = new RemoteV2()" will work fine; even better
because RemoteV2 provides an improved channel() method (override). New remotes will need
"BetterControl x = new RemoteV2()" to access the new methods. Plus other program changes to
take advantage of the new behaviors.

Jim ... ...


BEE MBA PMP SCJP-6
Steve Fahlbusch
Bartender

Joined: Sep 18, 2000
Posts: 557
    
    7

Jim -----

Very nice.

-steve
Vinoth Kumar Kannan
Ranch Hand

Joined: Aug 19, 2009
Posts: 276

Hey guys...Got a serious doubt here!


The above one works good, i know, because B extends A and 'a' is just a reference. With 'a' you can call all B's methods present in A and overridden,besides A's other methods. Right? Please correct me if I am wrong.



How does this work?
Isn't it like assigning ,

Now, this wont work,right? because a reference of B requires more info than what A has got?
Can we assign a superclass object to a subclass reference? I guess no...


OCPJP 6
Naresh Shanmugam
Ranch Hand

Joined: Jul 16, 2010
Posts: 84


Even the above would never work..
Thumb rule:
Left hand side must be super type and Right hand side can be either same type or sub type.
Jim Hoglund
Ranch Hand

Joined: Jan 09, 2008
Posts: 525
Vinoth : A question for you. If B extends A, then what "other methods"
does A have, beyond those available in B? Can you provide an example?

Jim ... ...
Vinoth Kumar Kannan
Ranch Hand

Joined: Aug 19, 2009
Posts: 276

sorry Jim...if B extends A, all A's methods would come into B!!

So, In A a = new B(); , 'a' can call A's overridden methods in B, and A's base methods. Correct?
Jim Hoglund
Ranch Hand

Joined: Jan 09, 2008
Posts: 525
If by "A's base methods" you mean those that are not overridden,
then I agree. But I am not familiar with the term "base methods".
Where do you see this terminology used?

Jim ... ...
Vinoth Kumar Kannan
Ranch Hand

Joined: Aug 19, 2009
Posts: 276

yeah..i was trying to mean the methods of A, not overridden!
'base methods' - i thought people would understand it as base class's methods..not a terminology certainly
Vinoth Kumar Kannan
Ranch Hand

Joined: Aug 19, 2009
Posts: 276

Jim, I did some workout regarding this reference assigning....and much clear now, except for one thing...
Please take a look at this,


Next I create a super class refernce,

So, we have agreed that baseObj can call/access only BaseClass's non-overridden methods and its overriden methods in SubClass?
I mean, it cannot call any of SubClass's new methods (methods not in BaseClass).

Then, I add this,


but now, i get the output as '3'!!
baseObj would not even had access to add() of SubClass!, but on assigning it to an Interface reference, it surprisingly calls that method!!


Anybody got any possible explanation?! Wondering how this executed..
Tyler Hanson
Greenhorn

Joined: Dec 31, 2009
Posts: 9
What you are doing is very tricky and also very dangerous.

Casts are interesting because there limited compiler checking if the type you are attempting to cast can actually be cast into whatever it is you are attempting to cast it too. For example, this will work



Now if you called any integer function, it would fail out. Go ahead and try this in your app.



Your app should then fail out.

This is because when you originally declared it at a NewSubClass, that is exactly what you have. Since you put it into a BaseClass object, the compiler would not let you call the new methods, but the object still had them. Since you cast it to the interface type, you then had access to those functions. It allowed it because those functions existed in NewSubClass (which is the actual type of the object in question).

So, basically what I am saying is that just because you package a subclass into the baseclass, it does not chop off the subclass methods, they simple are not available in a compiler check. They still exist, but can't be called directly from the object.

The concept is kind of similar to reflection (being able to access private and protected methods of classes. They exist and can be called if you go round a bout. Google java reflection for more info, but be prepared for some heavier lifting. It's a bit messed up at first).

Hopefully that answers your question, I'm not the best at explaining things.
Jim Hoglund
Ranch Hand

Joined: Jan 09, 2008
Posts: 525
So a good practice is to (almost) never downcast an object. There is a common
exception to this rule that's okay if the downcast is in conjunction with 'instanceof',
like this: Jim ... ...
Billy Vandory
Ranch Hand

Joined: Mar 23, 2010
Posts: 57
Jim Hoglund wrote:Billy : Let's construct a scenario to illustrate how polymorphism is really used. Consider a
hypothetical TV remote control.

Let's say that interface BasicControl declares methods: on(), off(), volume() and channel() and
that class RemoteV1 implements this interface; nothing extra, just the declared functions. The
methods available on 'x' would be the same for either "BasicControl x = new RemoteV1()" or
"RemoteV1 x = new RemoteV1()". But since we've been told to "design to the interface", we
deploy our program with the first "interface" definition.

Now it's time for an upgrade, adding methods mute() and sleepTimer(). Let's declare the new
methods in interface BetterControl which extends BasicControl. The new implementing class will
be RemoteV2 which extends RemoteV1. Also, let's say that an improved channel() method has
been developed and will be included in RemoteV2.

So what do we have? In writing RemoteV2 we didn't disturb the validated RemoteV1 methods
as they were inherited. The new mute() and sleepTimer() methods were coded and validated.
We decided, however, to include an overriding channel() method with better performance.

Older remotes can be upgraded by replacing RemoteV1 references with RemoteV2 and no other
changes. This works because "BasicControl x = new RemoteV2()" will work fine; even better
because RemoteV2 provides an improved channel() method (override). New remotes will need
"BetterControl x = new RemoteV2()" to access the new methods. Plus other program changes to
take advantage of the new behaviors.

Jim ... ...


Thanks for that excellent answer, Jim. If I have a class RemoteV1 and I want to add mute functionality as you mentioned, why can't I just add it to the RemoteV1 class? Adding a new method wouldn't break anything, so is this just a best practice?

And If I should extend V1, when does that happen? I mean, if I am in the progress of writing RemoteV1 and a day later, after I'm done implementing RemoteV1 I say "darn, I forgot the MUTE button", I wouldn't extend the class, I would just add the functionality to the RemoteV1 class, ? But if the app has gone through QA and is in production and an upgrade proposes a Mute button, then it would make sense to extend the class RemoteV1 at that point ? Just wondering how to decide when to extend a class... Seems like OO is more of an art than science. I try to make an effort to make sure my classes provide methods that fit that class and the class can take care of itself, but sometimes it feels like I am including every method under the sun and wonder if I shouldnt break it up a bit. So I ask myself, is there any advantage in breaking up a class? Could an invoker of my class benefit from instantiating a lesser version of my class? If so, I break it up. But this adhoc method of coding is a result of not pre-planning the work I suppose.....

Thanks again,

Billy
Tyler Hanson
Greenhorn

Joined: Dec 31, 2009
Posts: 9
I don't know what the "correct" answer to this question is, but my rule of thumb is that if the method is general enough to encompass most derived objects, then I add it. If it is a specific function to a specific type of the object, then I derive. Example, adding a Mute method to RemoteV1 is probably pretty ok since many remotes probably have a mute button. Lets suppose you have another remote that you are emulating. Lets say it is an Xbox360 media remote (since I have one). This has all the functions of a normal remote (on, off, volume, channel, mute), but it also has and Xbox guide button, and X,Y,A,B buttons. I would probably extend this into Xbox360Remote with the methods xboxGuide(), xButton(), etc because those are not closely related to a general remote.

Obviously, if you don't have the source to the original object, you have to extend.

But like you said, it is more of an art than a science. I try to write general classes and when i have a specific version of something, extend the simple class to add the non common code.

For example, on a project I am working on, i have a class called "Document". This is actually an abstract class. This class has many fuctions that are common to all of our documents that we store using this utility. Example on that is that all of the documents have a unique identifier, so there are setter/getter methods for that. From that I derive our specific document types, which have normal properties such as invoice id (not all documents have an invoice id).

Hope this helps,

Tyler
Jim Hoglund
Ranch Hand

Joined: Jan 09, 2008
Posts: 525
Is it helpful to consider a continuum of situations? At one extreme behaviors are
well understood, quite generic and generally reusable. So you have a concrete,
fully implemented class where overrides are rarely needed. At the other extreme,
there is a list of needed behaviors, but the implementation details depend heavily
on the application domain. This sounds more like an interface. And between these
two comes the abstract class, where some, but not all behaviors can be generically
implemented while others remain abstract methods.

Jim ... ...
Vinoth Kumar Kannan
Ranch Hand

Joined: Aug 19, 2009
Posts: 276

For this,

I get

Why is that we are getting the second 'true' here ?
BaseClass has nothing in common with MustImplementInterface.
All I did was,I first assigned the SubClass reference to BaseClass and then back to MustImplementInterface
Jim Hoglund
Ranch Hand

Joined: Jan 09, 2008
Posts: 525
The compiler is assuming that you know what you're doing with the cast. It does know,
however, that the object you just cast IS-A BaseClass and also IS-A SubClass. Casting
does not change the object's type.

Jim ... ...
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Polymorphism example - where would we ever use this construct?
 
Similar Threads
Simple question about OO
Large Java Class
why static should be avoided with web app?
static - old and new
Interesting article online about teaching OO