• 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
  • Devaka Cooray
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Jeanne Boyarsky
  • Tim Cooke
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Tim Moores
  • Mikalai Zaikin
  • Carey Brown
Bartenders:

Polymorphism example - where would we ever use this construct?

 
Ranch Hand
Posts: 57
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
..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.
 
Ranch Hand
Posts: 525
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 ... ...
 
Bartender
Posts: 612
7
Mac OS X Python
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Jim -----

Very nice.

-steve
 
Ranch Hand
Posts: 276
Netbeans IDE Chrome Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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...
 
Ranch Hand
Posts: 93
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


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
Posts: 525
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 276
Netbeans IDE Chrome Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 525
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 276
Netbeans IDE Chrome Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 276
Netbeans IDE Chrome Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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..
 
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 525
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 57
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 525
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 276
Netbeans IDE Chrome Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 525
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 ... ...
 
Could you hold this kitten for a sec? I need to adjust this tiny ad:
a bit of art, as a gift, the permaculture playing cards
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic