CS 61B Inheritance Spring 2021 Discussion 4: February 8, 2021
1
(a)
Raining Cats and Dogs
Below, four classes are defined. What would Java do after executing the main method in the testAnimals class? Next to each blank, if something is printed write it down. If there is an error, write whether it is a runtime error or compile time error, and then proceed through the rest of the code as if the erroneous line were not there.
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
public void greet() {System.out.println(“Animal ” + name + ” says: ” + this.noise);} public void play() {System.out.println(“Woo it is so much fun being an animal!”)}
}
public class Cat extends Animal { public Cat(String name, int age) {
super(name, age);
this.noise = “Meow!”; }
@Override
public void greet() {System.out.println(“Cat ” + name + ” says: ” + this.noise);}
public void play(String expr) {System.out.println(“Woo it is so much fun being a cat!” + expr)} }
public class Dog extends Animal { public Dog(String name, int age) {
super(name, age);
noise = “Woof!”;
}
@Override
public void greet() {System.out.println(“Dog ” + name + ” says: ” + this.noise);}
public class Animal {
public String name, noise; public int age;
1
2
3
4
5
6
7
8 9}
public Animal(String name, int age) { this.name = name;
this.age = age;
this.noise = “Huh?”;
2
Inheritance
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
public void play(int happiness) { if (happiness > 10) {
System.out.println(“Woo it is so much fun being a dog!”)
}
} }
public class TestAnimals {
public static void main(String[] args) {
Animal a = new Animal(“Pluto”, 10); Cat c = new Cat(“Garfield”, 6);
Dog d = new Dog(“Fido”, 4);
} }
a.greet();
c.greet();
d.greet();
c.play(); c.play(“:)”)
a=c;
((Cat) a).greet(); ((Cat) a).play(“:D”); a.play(14);
((Dog) a).play(12);
a.greet();
c = a;
// “Animal Pluto says huh?”
// “Cat Garfield says Meow!”
// “Dog Fido says Woof!”
// “Woo it is so much fun being an animal!”
// “Woo it is so much fun being a cat! :)”
// “Cat Garfield says Meow!”
// “Woo it is so much fun being a cat! :D”
// Compile time error.
// Runtime error.
// “Cat Garfield says Meow!”
// Compile time error.
(b) Spoiler alert! There is an error on the last line, line 60. How could we fix this error?
The compilation error on line 60 is because we are trying set c, which is of static type Cat to be equal to a, when the static type of a is Animal. Even though at runtime, a really does have dynamic type Cat, the compiler only sees static types so it doesn¡¯t believe that this assignment is valid. The compiler only sees that we are trying to set a Cat variable to point to an Animal, and an Animal isn¡¯t a Cat! One way to fix this error would be to cast a to be a Cat, such that the line reads c = (Cat) a;. This would be a valid cast, as the compiler agrees that a variable of static type Animal could potentially hold a Cat, and so our request is feasible. Because the cast works, then the assignment is also now valid because a variable of static type Cat can be told to point to the same thing as another variable of (temporary) static type Cat. At runtime, this line will be fine because we were telling the truth: a really is a Cat dynamically!
2 An Exercise in Inheritance Misery
Cross out any lines that result in compiler errors, as well as subsequent lines that would fail because of the compiler error. Put an X through runtime errors (if any). Don¡¯t just limit your search to main, there could be errors in classes A,B,C. What does D.main output after removing these lines?
System.out.println(“Am1-> ” + x); } System.out.println(“Am2-> ” + this.x); } x=99; }
System.out.println(“Bm2-> ” + x); }
System.out.println(“Bm2y-> ” + y); }
System.out.println(“Bm3-> ” + “called”); }
public class A {
public int x = 5; public void m1() { public void m2() { public void update() {
1
2
3
4
5 6}
7 public class B extends A{
8 public void m2() {
9 public void m2(int y){
10 public void m3() {
11 }
12 public class C extends B{
13 publicinty=x+ 1;
14 public void m2() {
15 \\ public void m4() {
16 public void m5() {
17 }
18 public class D {
19 public static void main
20 \\ B a0 = new A(); Dynamic type must be B or subclass of B
21 \\ a0.m1(); cascading: prev line failed, so a0 can’t be initialized
22 \\ a0.m2(16); cascading: prev line failed, so a0 can’t be initialized
23 A b0 = new B();
24 System.out.println(b0.x); [prints “5”]
25 b0.m1(); [prints “Am1-> 5”]
26 b0.m2(); [prints “Bm2-> 5”]
27 \\ b0.m2(61); m2 (int y) not defined in static type of b0
28 B b1 = new B();
29 b1.m2(61); [prints “Bm2y-> 61”]
30 b1.m3(); [prints “Bm3-> called”]
31 A c0 = new C();
32 c0.m2(); [prints “cm2-> 5”]
33 \\ C c1 = (A) new C(); Can’t assign c1 to an A
34 A a1 = (A) c0;
35 C c2 = (C) a1;
36 c2.m3(); [print Bm3-> called]
37 \\ c2.m4(); C.m4() is invalid
38 c2.m5(); [print Cm5-> 6]
39 ((C) c0).m3(); [print Bm3-> called]
40 \\ (C) c0.m2(); NOT RUNTIME ERROR This would cast the result of what the method returns and
it returns void therefore compile-time error
System.out.println(“Cm2-> ” + super.x); } System.out.println(“Cm4-> ” + super.super.x); } can’t do super.super
System.out.println(“Cm5-> ” + y); }
(String[] args) {
Inheritance 3
4
Inheritance
41
42
43 } 44 }
b0.update();
b0.m1(); [print Am1-> 99]