1

假设我有一个 GrandParentClass 被 ParentClass 继承,而 ParentClass 又被 ChildClass 继承。

为什么我只能“上链”而不能下链?

为什么我只能动态绑定“下链”而不是上链?

我正在寻找一些可以应用于这些问题的推理,而不仅仅是记住模式。我真的希望这不仅仅是一个“就是这样”的答案。

铸造示例:

ParentClass object = new ParentClass();
System.out.println((GrandParentClass)object);  //casting ChildClass throws compiler error 

动态绑定示例:

GrandParentClass = new ChildClass(); //Switching GrandParentClass with ChildClass throws run time error.
4

4 回答 4

2

可能很容易将其视为动物。可以说祖父母类是Animal,父类是Dog,子类是GermanShepherd

你的第一个例子是这样的:

Dog dog = new Dog();
System.out.println((Animal)dog);  
//casting GermanShepherd throws compiler error

狗总是可以是动物,但狗可能并不总是德国牧羊犬(它可能是贵宾犬)。

你的第二个例子:

Animal animal = new GermanShepherd(); 
//Switching Animal with GermanShepherd throws run time error.

同样,GermanShepherd 始终是动物,但动物可能不是 GermanShepherd(可能是乌龟)。

于 2013-04-29T02:26:11.177 回答
1

这些转换规则的一般推理(不仅在 Java 中)是继承允许您构建类树,而不仅仅是列表。换句话说,不是每个类型GrandParentClass的对象都一定是类型的对象,ParentClass也不是每个类型的对象ParentClass都一定是类型的ChildClass。您可以设想一种替代方法,它ParentClass2继承自GrandParentClass或简单地实例化类型为 的对象GrandParentClass。想象一下,如果您被允许访问一个GrandParentClass对象,就好像它是一个ChildClass具有所有方法和变量的对象一样,这些方法和变量只定义在上面,ChildClass而不是上面。没有有意义的解决方案。

因此,强制转换“链上”总是有意义的,因为继承关系在编译时是已知的。您的动态绑定示例是同一件事;您正在绑定“链上”(根本不是“链下”),因为您将派生类型对象分配给派生它的类型的引用。

于 2013-04-29T02:19:36.637 回答
0

ParentClass 有方法getWidget;ChildClass 具有继承的方法getWidget并声明了一个新方法getAnotherWidget。这意味着当编译器看到你有一个ChildClass对象时,它知道它ChildClass可以做所有ParentClass可以做的事情,因此将其ChildClass视为ParentClass. 然而,当编译器看到 a 时ParentClass,它并不知道它ParentClass有一个getAnotherWidget方法——你可以在运行时(通过 eg instanceof ChildClass)确定它,或者在编译时你可以告诉编译器“这个 ParentClass 对象真的是一个 ChildClass——相信我,我知道我在做什么”通过表演ChildClass childClass = (ChildClass)parentClass- 如果你错了,那么你会得到一个ClassCastException. 即使ChildClass只是继承自,您也需要执行此转换ParentClass不添加任何更多方法 - 编译器不够聪明,无法知道ChildClass基本上等同于ParentClass.

动态绑定只能以一种方式工作,因为ParentClass它不知道它的所有子类 - 您可能会在运行时加载其他继承类。相反,ChildClass知道它ParentClass是谁,因此它可以覆盖ParentClass的方法。(这就是为什么ChildClass可以调用super.getWidget()ParentClass不能调用的原因child.getWidget()——即使ParentClass知道它的所有子类是谁,它怎么知道你指的是哪个子类?与其加重语法负担,Java 更简单地要求你实例化一个ChildClass对象,如果你想使用它的方法而不是通过调用它们ParentClass

于 2013-04-29T02:19:44.653 回答
0

动态绑定和强制转换齐头并进。我理解他们的方式是ALWAYS从右到左阅读以确定您是否可以绑定和投射......例如:

object A          ←       object B
                           是一个

于 2013-04-29T02:21:15.633 回答