Java自学CS61B-Typing Puzzle
Java中的类型转换&编译器的识别(练英语ing,毕竟决定去CMU搬砖了)
课上老师举了个例子:我们想创建一个这样的层次类型关系。
Top | Object |
---|---|
Middle | Dog |
Bottom | ShowDog |
逻辑关系:
Dog is-an Object
ShowDog is-a Dog
那么我想尝试去实现这个课上的小puzzle,顺便可以梳理清楚很多相关的知识。
First Step: create an Object
We only need to create an empty Object as an interface, and when we create our Dog class, we use implements to call Object, so the Object interface is very simple:
public interface Object{
}
That’s all, What we need is just an empty interface called Object.
Second Step: create our Dog class
Because Dog class is the middle layer in the structure, so we need to implements Object. We also need to create a compiler to create our Dog, we need dog’s name, dog’s type, dog’s length and weight. So if we want to instantiate a new Dog type, we can do this:
new ShowDog("Mortimer", "Corgi", 25, 512.2);
We also need to create a method called bark()
, this method is very easy, we can only use System.out.println()
to print a bark!, the Dog class code is shown below:
public class Dog implements Object{
public String name;
public String type;
public int length;
public double weight;
public Dog(String n, String t, int l, double w){
name = n;
type = t;
length = l;
weight = w;
}
public void bark(){
System.out.println("Bark!");
}
}
Third Step: Create our ShowDog class
As the bottom layer, ShowDog class need to extends Dog class, and in ShowDog class we need to override our bark()
method:
public class ShowDog extends Dog{
public ShowDog(String n, String t, int l, double w) {
super(n, t, l, w);
}
@Override
public void bark(){
System.out.println("Oh, this owner is stupid!");
}
}
Final Step, do something interesting!
if we write our code like this, guess what happen?
public static void main(String[] args){
Object o2 = new ShowDog("Mortimer", "Corgi", 25, 512.2);
ShowDog sdx = ((ShowDog) o2);
sdx.bark();
Dog dx = ((Dog) o2);
dx.bark();
((Dog) o2).bark();
Object o3 = (Dog) o2;
o3.bark();
}
We will find something wrong, let’s we check our code line by line:
Line | Name | Static type (compile-time type) | Dynamic type (run-time type) |
---|---|---|---|
1 | o2 | Object | ShowDog |
2 | sdx | ShowDog | ShowDog |
3 | dx | Dog | Dog |
4 | (Dog) o2 | Dog | Dog |
5 | o3 | Object | Dog |
At first, I want to declare that the compiler only care about compile-time type, for example, if your code is:
ShowDog o2 = new Dog("Mortimer", "Corgi", 25, 512.2);
It cannot be compiled, because Dog is not a ShowDog !
OK, let we back to our code, o2’s static type is Object, the top layer in this structure, so it can contain any type in this structure. so line 1 can be compile!
Line 2, of course, ShowDog is a ShowDog
Line 3, Dog is a Dog
Line 4, Dog is a Dog
Line 5, Dog is a Object
Oh, we do not have any problem yet, why we have an error? We have to find something deeper.
public static void main(String[] args){
Object o2 = new ShowDog("Mortimer", "Corgi", 25, 512.2);
ShowDog sdx = ((ShowDog) o2);
sdx.bark();
Dog dx = ((Dog) o2);
dx.bark();
((Dog) o2).bark();
Object o3 = (Dog) o2;
o3.bark();
}
There is no problem in sdx.bark();
the result will be: Oh, this owner is stupid!
because in ShowDog, we override this method, and when we called bark();
in Dog or in ShowDog, the result always be the same.
so, dx.bark();
((Dog) o2).bark();
also work well, but when we turn to o3.bark();
something wired happened, o3’s static type is Object and we do not have bark();
method in Object, instead, we only have an empty interface, even if we have bark();
method in Dog and the o3’s Dynamic type is Dog, but compiler only care about the Static type! that’s why we have an error.
When we mask this line, everything will be fine! we’ll get what we expect: