The Artima Developer Community
Sponsored Link

Java Answers Forum
Polymorphism Question

11 replies on 1 page. Most recent reply: Feb 5, 2004 1:05 PM by twc

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 11 replies on 1 page
Kevin

Posts: 25
Nickname: doublek321
Registered: Jan, 2004

Polymorphism Question Posted: Jan 27, 2004 2:30 PM
Reply to this message Reply
Advertisement
In the file below (InheiritTests.java) there are 2 instantiated classes. One is of type "BaseClass" (stored in the variable called "baseClass") and the other is of type "DerivedClass" (stored in the variable called "derivedClass"). The output of the program is "DerivedClass.Method1" and "DerivedClass.Method1".

Since the output is the same regardless of the type my question is: does the type play any role at all in determining which method gets called? From this example it seems like it doesn't. It appears that only the class that gets instantiated has anything to do with the method that gets called. Is that accurate?


class BaseClass {
void method1() {
System.out.println("BaseClass.method1");
}
}

class DerivedClass extends BaseClass {
void method1() {
System.out.println("DerivedClass.method1");
}
}


class InheiritTests {
public static void main (String args[]) {
BaseClass baseClass = new DerivedClass();
baseClass.method1();

DerivedClass derivedClass = new DerivedClass();
derivedClass.method1();
}
}


MRoss

Posts: 2
Nickname: mross
Registered: Jan, 2004

Re: Polymorphism Question Posted: Jan 27, 2004 3:21 PM
Reply to this message Reply
Yes you're right. If you have something like
BaseClass baseClass;

You can make that reference refer to an instance of BaseClass or any subclass of BaseClass.

Sachin Joshi

Posts: 12
Nickname: aspire
Registered: Jan, 2004

Re: Polymorphism Question Posted: Jan 27, 2004 4:50 PM
Reply to this message Reply
Hi,

This is what is polymorphism. Base class variable can be used to denote Subclass instances.
But at runtime, there is one more feature of Java i.e. Dynamic Method Dispatch / Dynamic Binding. It means that, in polymorphism, at runtime
which method to call is decided depending on the ACTUAL OBJECT TYPE and the method signature.
So, in your example, though your calling method1() on BaseClass type reference, actually it is the reference for the object of type DerivedClass.
So, by Dynamic Method Dispatch, jvm looks for the method with signature in the DerivedClass and invokes it.

So the output is --> "DerivedClass.Method1" and "DerivedClass.Method1".

I hope it clears.

Sachin

Kevin

Posts: 25
Nickname: doublek321
Registered: Jan, 2004

Re: Polymorphism Question Posted: Jan 27, 2004 5:02 PM
Reply to this message Reply
Does this mean that there is no reason to use one of the statements below over the other? I mean, is there ANY situation where one would behave differently than the other or are they essentially equivalent?


BaseClass baseClass = new DerivedClass();
DerivedClass derivedClass = new DerivedClass();


In other words, is the right hand side the only thing that matters?

Also, what is the correct terminology to describe the thing to the left and right of the equal sign? I believe that the left hand side is the "type". What is the right hand side though? Is it called the "reference"? For example...


"Type" "reference?"
V V
BaseClass baseClass = new DerivedClass();

Sachin Joshi

Posts: 12
Nickname: aspire
Registered: Jan, 2004

Re: Polymorphism Question Posted: Jan 28, 2004 12:24 AM
Reply to this message Reply
hmm...it seems you have some basic queries about this kevin.

When you use new operator, you are creating an instance of the class. Now when you use Assignment operator i.e. "=",
you are assigning/storing a reference to that object in this varuable on left hand side of "=" operator. So,

BaseClass baseClass = new DerivedClass();
[Reference Variable Type][Reference variable name] = new [class name];


hope it clears.
Sachin


> Does this mean that there is no reason to use one of the
> statements below over the other? I mean, is there ANY
> situation where one would behave differently than the
> other or are they essentially equivalent?
>
>
> BaseClass baseClass = new DerivedClass();
> DerivedClass derivedClass = new DerivedClass();
>
>
> In other words, is the right hand side the only thing that
> matters?
>
> Also, what is the correct terminology to describe the
> thing to the left and right of the equal sign? I believe
> that the left hand side is the "type". What is the right
> hand side though? Is it called the "reference"? For
> example...
>
>

> "Type" "reference?"
> V V
> BaseClass baseClass = new DerivedClass();
>

Jonathon Brozny

Posts: 24
Nickname: jonathon
Registered: Oct, 2003

Re: Polymorphism Question Posted: Jan 28, 2004 12:35 AM
Reply to this message Reply
> Does this mean that there is no reason to use one of the
> statements below over the other? I mean, is there ANY
> situation where one would behave differently than the
> other or are they essentially equivalent?

There is a big reason to use one over the other. If later on you create another class like
SuperDerivedClass extends BaseClass{}

This class is maybe twice as efficient as the first one but if you referenced everything like
DerivedClass derivedClass = new DerivedClass();

and passed this object to, say 5 other classes that also reference it with DerivedClass. When you want to use your fancy new class you have to change every DerivedClass to SuperDerivedClass (6 places) so that you can use the new one.

On the other hand if you did it this way...
BaseClass baseClass = new DerivedClass();

all you have to do to use the new class is..
BaseClass baseClass = new SuperDerivedClass();

since the 5 methods that you passed this class to would already reference the object with BaseClass they can just use the new class.

Kevin

Posts: 25
Nickname: doublek321
Registered: Jan, 2004

Re: Polymorphism Question Posted: Jan 28, 2004 7:19 AM
Reply to this message Reply
> > Does this mean that there is no reason to use one of
> the
> > statements below over the other? I mean, is there ANY
> > situation where one would behave differently than the
> > other or are they essentially equivalent?
>
> There is a big reason to use one over the other. If later
> on you create another class like
>
> SuperDerivedClass extends BaseClass{}
> 

> This class is maybe twice as efficient as the first one


What are you referring to here when you say "the first one"?


> but if you referenced everything like
>
> DerivedClass derivedClass = new DerivedClass();
> 

> and passed this object to, say 5 other classes that also
> reference it with DerivedClass. When you want to use your
> fancy new class you have to change every DerivedClass to
> SuperDerivedClass (6 places) so that you can use the new
> one.


If I understand correctly you're saying that it's foolish to declare a parameter using a derived class because it can cause maintenance issues later on. So, for example, the method below would be a bad idea...


void someMethod (DerivedClass abc) { /* do something  */ }



However, couldn't the same method be written like this (below) and still work regardless of if you had created the variable with


"BaseClass baseClass = new BaseClass()"


...or...

"DerivedClass baseClass = new BaseClass()"



If so, then I still don't see a compelling reason to use one over the other. Am I still missing the big picture?


void someMethod (BaseClass abc) { /* do something  */ }

Daniel Yokomizo

Posts: 22
Nickname: dyokomiso
Registered: Sep, 2002

Re: Polymorphism Question Posted: Jan 28, 2004 11:10 AM
Reply to this message Reply
>
> If I understand correctly you're saying that it's foolish
> to declare a parameter using a derived class because it
> can cause maintenance issues later on. So, for example,
> the method below would be a bad idea...
>

>
> void someMethod (DerivedClass abc) { /* do something  */
> }
> 

>
> However, couldn't the same method be written like this
> (below) and still work regardless of if you had created
> the variable with
>

>
> "BaseClass baseClass = new BaseClass()"
> 

>
> ...or...
>

>
> "DerivedClass baseClass = new BaseClass()"
> 

>
> If so, then I still don't see a compelling reason to use
> one over the other. Am I still missing the big picture?
>

>
>
> void someMethod (BaseClass abc) { /* do something  */ }
> 


I'll try to answer your questions changing the examples. In class-based OOPLs, like Java, classes (and interfaces) are used to create classification hierarchies, starting from more generic classes and ending in specific instances. Let's look at part of the hierarchy of java.util.Collection:

// super-type of collections
interface Collection {
}
/* super-type of collections that can be indexed.
 */
interface List extends Collection {
}
/* super-type of collections with set-like behavior 
 * (i.e. no duplicates)
 */
interface Set extends Collection {
}
/* super-type of collections with set-like behavior 
 * and ordered iteration (i.e. iterator.next() always
 * gives "smaller" elements first, obeying 
 * java.lang.Comparable.compareTo() ordering)
 */
interface OrderedSet extends Set {
}
 
public int countDuplicatedElements(Collection c) {...}
public List sort(List aList, Comparator order) {...}
public Set getAllDepartments(Set employees) {...}
public void processJobs(OrderedSet thingsToDo) {...}


So we have four types in our hierarchy (in this case they are interfaces not classes but the rationale is similar) representing the problem we want to model. The four methods use different types of this hierarchy as parameters, according to their preconditions:

- countDuplicatedElements doesn't depend on any assumptions about concrete type of c;
- sort needs a Collection that can be indexed, so it can sort its elements. The parameter is a List to express this need (also Collection has no Object get(int) method, but List has);
- getAllDepartments works under the assumption that the collection of employees has no duplicates, the parameter type works as a restriction/documentation, because the method doesn't use any operations on employees that aren't from Collection;
- processJobs needs to do the tasks respecting their priority, which is given by some comparison operation, also we should be able to do each task once and only once. Again the parameter type works as a restriction/documentation, because the method use just the Iterator iterator() method from Collection on thingsToDo and not the fancy methods specific to OrderedSet.

The conclusion is, if your method should work with the base class (i.e. no assumptions about the subclasses invariants or doesn't use methods from subclasses) make it so. Otherwise if it needs some restriction and/or specialized operation type it using the subclass.

twc

Posts: 129
Nickname: twc
Registered: Feb, 2004

Re: Polymorphism Question Posted: Feb 4, 2004 6:33 AM
Reply to this message Reply
Here is an example that helped me understand polymorphism. Imagine that you have a class called Animal which in turn has several subclasses - say Dog, Cat and Bird. All of the classes have a speak() method (this is critical). In the Animal class, the method may or may not do anything, but the others print an appropriate word (i.e. "woof", "meow" and "tweet"). Lastly imagine that the code shown below is in an application.

//example application snippet
Animal[] pets = new Animal[3];
pets[0] = new Dog();
pets[1] = new Cat();
pets[2] = new Bird();
for(int i = 0; i < pets.length; i++)
pets.speak();
//end example

The code would print the three words without the need to typecast. Thanks to polymorphism, each object in the Animal array "knows" what kind of Animal object it is, so it invokes the appropriate speak() method.

If you use a GUI, a similar process takes place every time the GUI repaints itself. A Container subclass (i.e. Frame) keeps an array of its Components (which could be anything from Panels or Buttons to user-created custom subclasses). All of these will have a paint(Graphics g) method, and many (most?) will have that method overridden.

There is no way the code in the Container class could be written to typecast all of the different kinds of Components in the array. But, thanks to polymorphism, casting is not needed. Each of the various objects in the array will know what they are and invoke their own paint method when called upon to do so.

I hope his helps.

tom

Vincent O'Sullivan

Posts: 724
Nickname: vincent
Registered: Nov, 2002

Re: Polymorphism Question Posted: Feb 5, 2004 9:03 AM
Reply to this message Reply
> Here is an example that helped me understand polymorphism.
> Imagine that you have a class called Animal which in turn
> n has several subclasses - say Dog, Cat and Bird. All of
> the classes have a speak() method (this is critical).

It's not actually critical that all the derived classes override the speak() method in the Animal class. In effect, the Animal's speak() method is a default method that is called, unless it is overridden by one of the subclasses.

Vince.

twc

Posts: 129
Nickname: twc
Registered: Feb, 2004

Re: Polymorphism Question Posted: Feb 5, 2004 12:27 PM
Reply to this message Reply
If you look at the example that I gave, pets[] is an array of Animal objects. If the Animal class doesn't have a speak() method, then the line

pets.speak()

will not compile!

twc

Posts: 129
Nickname: twc
Registered: Feb, 2004

Re: Polymorphism Question Posted: Feb 5, 2004 1:05 PM
Reply to this message Reply
I reread your post and realized that I misinterpreted what you were saying. You are correct, that the subclasses could get by without a speak() method. What I *meant* to say is that it is critical that the Animal class have a speak() method, and usual that the others would override it.

Mea Culpa

tom

Flat View: This topic has 11 replies on 1 page
Topic: How to make JPanel scrollable? Previous Topic   Next Topic Topic: Eclipse runtime workbench

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use