试图从继承的角度理解转换和动态绑定

时间:2013-04-29 02:10:08

标签: java inheritance casting dynamic-binding

假设我有一个由ParentClass继承的GrandParentClass,它由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 个答案:

答案 0 :(得分: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.

同样地,德国牧羊犬将永远是动物,但动物可能不是德国牧羊犬(可能是乌龟)。

答案 1 :(得分:1)

这些转换规则(不仅仅是Java)的一般推理是继承允许您构建类的树,而不仅仅是列表。换句话说,并非GrandParentClass类型的每个对象都必须是ParentClass类型的对象,并且类型ParentClass中的每个对象都不一定是ChildClass类型的对象。您可以设想从ParentClass2继承的替代GrandParentClass,或者只是实例化GrandParentClass类型的对象。想象一下,如果允许您访问GrandParentClass对象,就好像它是一个ChildClass对象,其中包含仅在ChildClass但不在上面定义的所有方法和变量,会发生什么。没有有意义的解决方案。

因此,构建“向上链”总是有意义的,因为继承关系在编译时是已知的。你的动态绑定示例是一样的;您正在绑定“链上”(根本不是“链中”),因为您要将派生类型对象分配给它派生类型的引用。

答案 2 :(得分:0)

ParentClass的方法为getWidget; ChildClass具有继承的方法getWidget并声明了一个新方法getAnotherWidget。这意味着当编译器发现您有一个ChildClass对象时,它知道ChildClass可以执行ParentClass可以执行的所有操作,因此将ChildClass视为一个安全的做法是安全的。 ParentClass。但是,当编译器看到ParentClass时,知道ParentClassgetAnotherWidget方法 - 您可以在运行时确定(通过例如{ {1}}),或者在编译时你可以告诉编译器“这个ParentClass对象真的是一个ChildClass - 相信我,我知道我正在做什么”通过执行一次演员instanceof ChildClass - 如果你错了然后你会得到一个ChildClass childClass = (ChildClass)parentClass。即使ClassCastException仅仅继承ChildClass而不添加任何其他方法,您也需要执行此转换 - 编译器不够聪明,不知道ParentClass基本上等同于{{1} }}

动态绑定只能以一种方式工作,因为ChildClass不知道它的所有子节点 - 您可以在运行时加载其他继承类。相比之下,ParentClass知道其ParentClass是谁,因此它可以覆盖ChildClass的方法。 (这就是为什么ParentClass可以拨打ParentClass,但ChildClass无法拨打super.getWidget()的原因 - 即使ParentClass知道所有的孩子都是谁,怎么会知道你指的是哪个子类?如果你想使用它的方法而不是通过child.getWidget()来调用它,那么Java要求你实例化一个ParentClass对象,而不是让语法负担过重。 / p>

答案 3 :(得分:0)

动态绑定和铸造齐头并进。他们我理解它是ALWAYS从右到左阅读,以弄清楚你是否可以绑定和演员......例如:

object Aobject B