Polymorphism and Collections

advertisement
Chapter 9:
Polymorphism
Coming up: Creating Objects Revisited
Today’s lecture
• Review polymorphism
• examples
Polymorphism
• Polymorphism is an core object-oriented concept that
allows us to create a variable with "more than one
form"
• We've seen this throughout the semester: with
inheritance, interfaces
• If an object is of type Student, where Student extends
Person, we could say
Object thing = getStudent();
Person person = getStudent();
Student jane
= getStudent();
Design in Java
• Consider object.toString()
• The question is, what does the
toString method actually do?
• That is, what does the code for
toString look like when it is called
on some object?
• The answer is, "it depends"
• It depends on what is the actual type
of the object, in memory
• This may or may not be the type that
the reference to the object was given
toString and polymorphism
• import java.util.*;
public class Test{
public static void main(String[] args){
ArrayList list = new ArrayList();
list.add(new Object());
list.add(new String("Kinga"));
list.add(new Integer(3));
list.add(new ArrayList());
for(Object o : list){
System.out.println(o.toString());
System.out.println(o.getClass());
}
}
}
Will this work?
• import java.util.*;
public class Test{
public static void main(String[] args){
ArrayList list = new ArrayList();
list.add(new Object());
list.add(new String("Kinga"));
list.add(new Integer(3));
list.add(new ArrayList());
for(int i = 0; i < list.size(); i++){
String o = ((String)list.get(i));
System.out.println(o);
}
}
}
Binding
• Consider the following method invocation:
obj.toString();
• At some point, this invocation is bound to the definition
of the method that it invokes
• i.e., we figure out which toString we actually run
• If this binding occurred at compile time, then that line
of code would call the same method every time
• However, Java defers method binding until run time -this is called dynamic binding or late binding
Polymorphism
•The term polymorphism literally means "having
many forms"
•A polymorphic reference is a variable that can
refer to different types of objects at different
points in time
•The method invoked through a polymorphic
reference can change from one invocation to the
next
•All object references in Java are potentially
polymorphic
References and Inheritance
•Assigning a child object to a parent reference is
considered to be a widening conversion, and can
be performed by simple assignment
•Assigning a parent object to a child reference
can be done also, but it is considered a
narrowing conversion and must be done with a
cast
•The widening conversion is the most useful
Which of the following are valid in Java?
• Person jane = new Person();
• Person jane = new Object();
• Person jane = new Person();
jane = new Student(); //child class*
• Student eric = new Student();
Person jane = eric;
• Student eric = new Student();
Person jane = (Person)eric;
• Student eric = new Person();
• Person jane = new Person();
Student eric = jane;
• Person jane = new Person();
Student eric = (Student)jane;
* Student is a child class of Person
Solution
•Java only honors an assignment where the
contract between interfaces is honored
•Pick the most surprising/confusing example from
the previous slide and see how the interface
was/was not honored
→ or try it out in Eclipse
So, does Java even care about types?
•It seems like we can assign an object to a
reference that is not the same type as the object
itself
•Yes, we can! As long as it makes sense to…i.e.,
the contract is honored
•Java is smart
•It knows the actual type of the object
in memory
•It allows you to be flexible and use
any compatible types
Flexibility
• Can you think of an example where this might be
useful? (How have we used it, already?)
• Imagine we have a collection of animals of different
types…
• Lets us write specialized code for every animal,
rather than writing messy code in one animal class
that is supposed to handle all the different types of
animals
• How does Java know what kind of animal it is when
the speak method is called?
Polymorphism and Inheritance
• Widening conversion:
• Object object = new String("kinga");
• Narrowing conversion (will compile):
• Person jane = new Person();
Student eric = (Student) jane;
• Illegal narrowing conversion:
• Person jane = new Person();
Student eric = jane;
• Why?
Polymorphism via Interfaces
• Suppose two classes, Philosopher and Dog, both
implement the Speaker interface, providing distinct
versions of the speak method
• In the following code, the first call to speak invokes
one version and the second invokes another:
Speaker guest = new Philospher();
guest.speak();
guest = new Dog();
guest.speak();
Question
•What is the difference between interfaces
and inheritance?
How does Java know the type of an object
at runtime?
• This information is stored in memory, along with
the contents of the object
• Why can't this sort of thing be decided at compile
time?
• A compiler can only check for certain things, and
implementing polymorphism correctly isn't one of
them
Imagine a collection of Animals
• ArrayList animals = DB.getAnimals();
• animals contains Elephants, Lions, and Bears
for(int i = 0; i < animals.size(); i++)
((Animal)animals.get(i)).speak();
• Will call the specialized speak method
• Collections are a natural way to use polymorphism in Java
• What else could we want to do this array? Why are collections
useful?
Collection interfaces
•ArrayList implements the Collection
interface
•Also implements List, which extends
Collection
•Why use a Collection?
•Collections.sort(List) can sort an
ArrayList according to the natural ordering
of its elements
•Elements have a natural ordering if they’re
Comparable
Why do we care about sorting?
we're dealing with information
• Need some way to search it,
• Therefore need some way to index it,
• Therefore need some way to order the items
(unless we want terribly long searches)
• Comparing and searching are at the heart of many
applications
• Maintaining a sorted list helps these operations go faster
Download