W4: Polymorphism
Please submit your answers to the questions as comments in a W4.md
file you’ll be writing in this lecture.
Grading rubric and submission
When you are done, submit your W4.md
file to BB.
You will be graded on the following:
Item | Points |
---|---|
Answers are correct | 100 |
Questions
0
Define polymorphism in the context of Java and provide one example where it is valuable.
Answer
Polymorphism in Java allows multiple implementation of the same interface. One example will be the Point
and CustomPoint
classes we implementated in class where we can have a toString()
method in both Point
and CustomPoint
that prints out different information.
1
Consider the following program from the class notes
public class Ex3 {
public static void main(String[] args) {
Random rand = new Random(System.currentTimeMillis());
Point v = new Point(3, 4);
= new LabPoint(5, 2, "A");
LabPoint w String x = "I'm a string";
Scanner y = new Scanner(System.in);
Object u;
int i = rand.nextInt(4);
if( i == 0 )
= v;
u else if( i == 1 )
= w;
u else if( i == 2 )
= x;
u else
= y;
u System.out.println(u.toString()); //<--
}
}
Explain how polymorphism makes this program possible.
Answer
Since every class that does not have the extends
keyword implicitly extends the Object
class, the Object u
declaration makes u
capable of “morphing” into any of the 4 variables v, w, x, y
.
2
What is the output of this program? You should be able to do this without running the program!
class A {
public String toString(){
return "A";
}
}
class B extends A{
public String toString() {
return "B";
}
}
class C extends A {
public String toString() {
return super.toString();
}
}
class D extends C {
public String toString() {
return super.toString();
}
}
public class tmp {
public static void main(final String args[]) {
= new D();
D d System.out.println(d.toString());
}
}
Answer
The output is A
because class D
extends class C
and class C
extends class A
where both classes C, D
have their toString()
function return super.toString()
and the toString()
method of class A
returns a single character A
.
3
What is the output of this program? You should be able to do this without running the program!
class A {
public String toString() {
return "A";
}
public String fancyToString() {
return "~~A~~";
}
}
class B extends A {
public String toString() {
= this;
A letterA return letterA.fancyToString();
}
public String fancyToString() {
return "~~B~~";
}
}
public class LetterPrinter {
public static void main(final String args[]) {
= new B();
B letterB System.out.print(letterB.toString() + " ");
= letterB;
A letterA System.out.println(letterA.toString());
}
}
Answer
- The output of the program is
~~B~~ ~~B~~
. - With polymorphism,
letterB.toString()
will makeletterA
ofA letterA = this;
inclass B
toclass B
, which results inletterA.fancyToString();
return~~B~~
. Similarly, in the main function, whenA letterA = letterB
, it is morphed intoclass B
rather thanclass A
, resulting inletterA.toString()
give the same output as the first print statement~~B~~
.
4
What is the output of this program? You should be able to do this without running the program!
class A {
public String toString() {
return "A";
}
public String fancyToString() {
return "~~A~~";
}
}
class B extends A {
public String fancyToString(){
return "~~B~~";
}
}
public class LetterPrinter {
public static void main(final String args[]) {
= new B();
B letterB System.out.print(letterB.toString() + " ");
= letterB;
A letterA System.out.println(letterA.toString());
}
}
Answer
- The output of this program is
A A
. - Note that
class B
does not have atoString()
method, which means callingletterB.toString()
will result in thetoString()
method ofclass A
sinceclass B extends A
. Similarly, althoughA letterA = letterB
morphedletterA
toclass B
, it still uses thetoString()
method ofclass A
.
5
What happens to the object letterA
points to in memory when you do the cast below?
class A {
public String toString() {
return "A";
}
}
class B extends A {
public String toString() {
return "B";
}
}
public class PolymorphicOverload {
public static void main(String args[]) {
= new B();
B letterB = (A) new B();
A letterA }
}
Answer
The cast will have no effect; letterA
still points to an object of type B
in memory. The cast is not necessary here, and in general is simply a promise to the compiler, not something that updates memory.
6
Consider the following classes
public class A {
public int foo() {
return 42;
}
public int bar() {
return foo() + 8;
}
}
public class B extends C {
public int foo() {
return 41;
}
public char baz() {
return 'y';
}
}
public class C extends A {
public char baz() {
return 'x';
}
}
public class D extends A {
public int bar() {
return 7;
}
}
public class E extends C {
public int bar() {
return foo() + 20;
}
}
Consider a mystery function that returns a object of the given class. You do not know the definition of the mystery function, other than it compiles properly and returns an object of the class. For each of the following method calls marked below, indicate the value of the output, if the output cannot be determined, or if there is an error.
= mysteryA(); //<-- mystery function, this line compiles (the below may not!)
A a System.out.println(a.foo()); //<-- Mark A.1
System.out.println(a.bar()); //<-- Mark A.2
System.out.println(a.baz()); //<-- Mark A.3
= mysteryB(); //<-- mystery function, this line compiles (the below may not!)
B b System.out.println(b.foo()); //<-- Mark B.1
System.out.println(b.bar()); //<-- Mark B.2
System.out.println(b.baz()); //<-- Mark B.3
= mysteryD(); //<-- mystery function, this line compiles (the below may not!)
D d System.out.println(d.foo()); //<-- Mark D.1
System.out.println(d.bar()); //<-- Mark D.2
System.out.println(d.baz()); //<-- Mark D.3
Answer
A.1 : Compiles, Output not deterministic
A.2 : Compiles, Output not deterministic
A.3 : Doesn't Compile, No output
B.1 : Compiles, Output is 41
B.2 : Compiles, Output is 49
B.3 : Compiles, Output is y
D.1 : Compiles, Output is 42
D.2 : Compiles, Output is 7
D.3 : Doesn't Compile, No output
7
What is the difference between a class
and an abstract class
? From a software engineering perspective, why would you ever want to use an abstract class instead of a regular class?
Answer
An abstract class
can only be inherited by another class and can not be directly instantiated. A class
can be instantiated in most contexts, and still inherited by other classes as well. abstract class
es must also be implemented before code will compile.
You would prefer an abstract class when you want to enforce that the abstract class’ constructor can/should never be called.
8
If you were to create an abstract class for a Car
– what features could be defined in the implemented class vs. what could be defined in the abstract class? Provide justifications for your design.
Answer
Features such as car brand, model, year, and other attributes that would be highly variable would be defined in the class implmentation. Other functions that would be mostly fixed and more deterministic across different class definitions, such as toString
and functions that get or set values would be defined in the abstact
class.
9
What is the instanceof
operator in Java? When should you use it? When should you not use it?
Answer
The instanceof
operator allows you to look up the runtime type of any object, which may be different than the compile-time type of the same object.
It’s useful when you want to be sure that a cast you plan to do is compatible with the runtime type of the object. However, with good OOP, you should not be relying on this operator for situations that could be better handled by elegant polymorphism.