JS++ 上转换和下转换
现在我们已经了解了子类型和静态与动态多态性,我们可以学习上移和下移的内容。
上传和下传是基于类型关系的。换句话说,如果你有 “动物 “类型的数据,你可以把它 “下移 “到它的子类型 “狗”。相反,如果你有 “狗 “类型的数据,你可以将它 “上投 “到它的超类型 “动物”。然而,你不能将这两种类型的数据投到 “int”,因为 “int “和 “动物 “或 “狗 “之间没有类型关系。
既然我们现在对编译时与运行时的多态性有了了解,也知道了当数据类型被指定为 “动物 “时,编译器为什么以及如何解决 “渲染 “方法,让我们恢复我们的main.jspp代码。
import Animals;
Animal cat1 = new Cat("Kitty");
cat1.render();
Animal cat2 = new Cat("Kat");
cat2.render();
Animal dog = new Dog("Fido");
dog.render();
Animal panda = new Panda();
panda.render();
Animal rhino = new Rhino();
rhino.render();
你会记得,这是渲染我们所有动物的代码,但我们不再在鼠标上得到动物的名字。纠正这个问题的一个方法是用一个下划线。
import Animals;
Animal cat1 = new Cat("Kitty");
((Cat) cat1).render();
Animal cat2 = new Cat("Kat");
((Cat) cat2).render();
Animal dog = new Dog("Fido");
((Dog) dog).render();
Animal panda = new Panda();
panda.render();
Animal rhino = new Rhino();
rhino.render();
类型转换的语法是:。
(type) expression
比如说。
(int) 100
在我们修改后的main.jspp代码中,之所以有额外的小括号,是因为我们想让类型转换优先,以便在调用’render’方法之前发生转换。更多细节请参见JS++运算符优先级表。
如果你现在编译并运行代码,你应该看到当你把鼠标悬停在猫和狗的图标上时,它们会再次显示它们的名字。
为了说明上投,我们也可以把其中一只猫投到 “动物 “类型。在这只猫身上调用’render’方法将意味着它使用’动物’类的render()方法,其中不包括名字。
import Animals;
Animal cat1 = new Cat("Kitty");
((Cat) cat1).render();
Cat cat2 = new Cat("Kat");
((Animal) cat2).render();
Animal dog = new Dog("Fido");
((Dog) dog).render();
Animal panda = new Panda();
panda.render();
Animal rhino = new Rhino();
rhino.render();
请注意,我把’cat2’的类型改回了’猫’,以说明上推法。从那里,我把’cat2’上传到’动物’。如果你现在编译代码,你会注意到第一只猫(”Kitty”)在鼠标移动时显示了它的名字,但是第二只猫(”Kat”)却没有同样的行为。
虽然我们能够使用转换来解决正确的 “render “方法,但这并不是解决该方法的最优雅的方式。例如,如果我们有一个 “动物 “对象的数组,我们的循环将被嵌套在 “if “语句中,进行 “instanceof “检查和随后的类型转换。这并不理想,会导致代码难以阅读。有一个更优雅的方法:虚拟方法。