Next we’ll continue to practice with inheritance. We’ll also introduce a new big (literally) idea—polymorphism. Polymorphism may sound scary, but it’s not, and we’ll work it out together like we always do, using a lot of examples.
Let’s look at another example of puzzling Java code together:
Polymorphism is a big word, and sounds a bit scary. But it’s actually quite straightforward. Let’s work it out together starting with the Wikipedia definition:
In programming languages and type theory, polymorphism is the provision of a single interface to entities of different types
One way to think about polymorphism and Java inheritance is to consider “is a” relationships.
For example, every instance of any Java class
“is a” Object
, because every class
is a subclass of Object
.
Other “is a” relationships depend on inheritance relationships established with extends
:
One frequent confusion regarding polymorphism has to do with overriding inherited methods. Let’s look at how that works:
When we create an instance of a class, we can save it into a variable of any type that it can morph into:
This is referred to as upcasting.
Java will automatically upcast an instance to any of its supertypes.
Because Dog
extends Pet
and Pet
extends Object
, a Dog
can be stored in a Dog
, Pet
, or Object
variable.
However! The type of the variable determines what we can do with that object. Let’s look at how.
Don’t worry if this seems a bit fuzzy now. We’ll return to this topic a few lessons from now when we discuss object references.
instanceof
instanceof
Consider the type hierarchy established below:
Given a Pet
variable, it might refer to a Dog
, a Cat
, a Pet
or some other kind of pet!
Is there a way that we can tell?
Yup!
To test if an object is an instance of a particular class, we use the instanceof
operator.
And, once we determine that cat
is actually an instance of Cat
, there is another step that we have to take before we can call meow
.
Let’s examine how that works:
Create a public class named Greeter
that provides a single class method named
greet
.
greet
should accept a single parameter, a Person
to greet, and return a String
, the greeting.
Depending on what kind of person it is, you should greet them differently:
Professor
—for instance, one named "Geoff"—you should greet them "Hi Professor Geoff"Student
—for instance, one named "Friendly"—you should greet them "Hey Friendly, you are not
alone!"Staff
, then they will have a String
role you can retrieve using getRole
.
For example, if their role is "advising" their name is "Chuchu", you should greet them "Thanks Chuchu for all your
help with advising".All Person
s have a name that you can retrieve using getName
.
If the person is null
or not one of the kinds of people described above, return null
.
Do not solve this problem using method overloading.
And do not hard-code the answers.
Your solution should work for any Professor
, Student
, or Staff
.
The last two lessons have been pretty loaded with new ideas and concepts! Exciting, but also enough to make your head spin.
Don’t worry. Over the next two lessons we’ll slow down and review what we’ve learned. And then, over the lessons that follow we’ll have even more opportunities to integrate this knowledge, but with a small twist. So be patient. This won’t all make sense immediately. But it will all make sense eventually.
Create a public class named Orderer
that provides a single class method named
order
.
order
should accept a single parameter, a Restaurant
to order from, and return a String
, a comment on your
order.
Depending on which subclass of Restaurant
it is, you should respond differently:
Fancy
restaurant—for instance, with name
"MIGA"—you should order "At MIGA I'll order
something
inexpensive"FastFood
restaurant, for instance, with with name
"Chipotle"—you should order "At
Chipotle I'll order
something healthy"Vegan
restaurant, then it will have a String
property cuisine you can retrieve
using getCuisine
.
For example, if it its cuisine is "Thai" and name
is "Vegan Delight", you should order "At Vegan Delight I'll
order delicious Thai
food".All Restaurant
s have a name that you can retrieve using getName
.
If the restaurant is null
or not one of the kinds described above, return null
.
Do not solve this problem using method overloading.
And do not hard-code the answers.
Your solution should work for any Fancy
, FastFood
, or Vegan
instance.
Note that we are not implying that there are not fancy vegan restaurants or fancy fast food restaurants or vegan fast-food restaurants. If anything, the ability of real entities to resist strict classification is one of the limitations of Java's object model.
Create a public class named Visitor
that provides a single class method named
visit
.
visit
should accept a single parameter, a Place
to visit, and return a String
, a remark on how to visit that
place.
Depending on which subclass of Place
it is, you should respond differently.
Every place has a name you can retrieve using getName
.
assert
that the passed place is not
null`.
Building
—for instance, one named "Siebel"—you should respond "Let's go to the Siebel building."Park
—for instance, one named "West Side"—you should respond "Let's visit West Side park."Restaurant
, then it will have a String
property cuisine you can retrieve
using getCuisine
.
For example, if the cuisine is "thai" and the name is "Thara Thai", you should respond "Let's try thai food at Thara
Thai."If the place is not one of the kinds described above, return "Whoa, mysterious!".
Do not solve this problem using method overloading!
And do not hard-code the answers.
Your solution should work for any Building
, Park
, or Restaurant
.
Note that many restaurants are also buildings. The tendency of real entities to resist strict classification is one of the limitations of Java's object model.
Need more practice? Head over to the practice page.