📜  JS++ |上倾和下倾

📅  最后修改于: 2022-05-13 01:54:49.006000             🧑  作者: Mango

JS++ |上倾和下倾

现在我们了解了子类型和静态与动态多态性,我们可以了解向上转换和向下转换。

向上转换和向下转换基于类型关系。换句话说,如果您有类型为“动物”的数据,则可以将其“向下转换”为它的子类型“狗”。相反,如果您有类型为“Dog”的数据,则可以将其“向上转换”到其超类型“Animal”。但是,您不能将任一类型的数据转换为“int”,因为“int”与“Animal”或“Dog”之间没有类型关系。

由于我们现在了解了编译时与运行时多态性,以及当数据类型指定为“Animal”时编译器为何以及如何解析“render”方法,让我们恢复我们的 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' 方法将意味着它使用不包含名称的 'Animal' 类 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”的类型改回“Cat”以说明向上转换。从那里,我将“cat2”升级为“动物”。如果您现在编译代码,您会注意到第一只猫(“Kitty”)的名字显示在鼠标悬停上,但第二只猫(“Kat”)没有相同的行为。

虽然我们能够使用强制转换解析正确的“渲染”方法,但这并不是解析该方法的最优雅的方式。例如,如果我们有一个“Animal”对象数组,我们的循环将嵌套在“if”语句中,执行“instanceof”检查和随后的类型转换。这并不理想,会导致代码难以阅读。还有一种更优雅的方式:虚方法。