class A {
void f1() { //this holds address of object of B
System.out.println("A f1");
}
void f2() {
System.out.println("A f2");
}
}//A
class B extends A {
void f3() { //new method
System.out.println("B f3");
}
void f2() { //this holds address of object of B
System.out.println("B f2 starts");
f3(); //this.f3()
System.out.println("B f2 ends ");
} } //B
class TypeCmptbl {
public static void main(String args[]) {
A ref; //reference of A
ref = new B();//Object of B
//ref.inherited() allowed
ref.f1();
//ref.overridden() allowed
ref.f2();
//ref.newMembersOfChild() not allowed
//ref.f3();
}//main
}
...
SuperClass superClass1 = new SuperClass();
SuperClass superClass2 = new SubClass();
...
superClass1.someMethod(); // SuperClass version is called
superClass2.someMethod(); // SubClass version is called
....
4条答案
按热度按时间vtwuwzda1#
继承创建类型兼容性。它允许一个超类引用引用子类的对象。(反之则不成立)。
引用子类对象的超类引用只能用来访问子类继承和覆盖的方法,子类中新定义的成员不能通过超类引用访问。
考虑以下语句
这里ref是类A的引用,它具有类B的对象的地址,f2()是一个重写的方法。
当编译器检测到这样的语句时,它不会将函数调用与任何定义绑定,而只是验证调用。
这种调用的绑定留给运行时环境。在程序运行时,系统识别对象的数据类型,并将函数调用与对象类提供的函数定义绑定。函数调用与函数定义之间的这种类型的绑定称为"后期绑定"或"运行时绑定"或"运行时多态性"或"动态方法调度"。
xghobddn2#
动态绑定指的是编译器不能解析调用的情况,绑定只能在运行时完成。让我们试着理解这一点。假设我们有一个名为“SuperClass”的类,另一个名为“SubClass”的类扩展了它。现在,“SuperClass”引用也可以赋给“SubClass”类型的对象。如果我们有一个方法(比如说'someMethod()'),而我们在'SubClass'中重写了该方法,则对'SuperClass'引用的该方法的调用只能在运行时解析,因为编译器无法确定该引用在运行时将指向什么类型的对象。
在这里,我们可以看到,尽管对象引用superClass 1和superClass 2都只是“SuperClass”类型,但在运行时它们分别引用“SuperClass”和“SubClass”类型的对象。
因此,在编译时,编译器无法确定在这些引用上对方法'someMethod()'的调用实际上引用了该方法的哪个版本--超类版本还是子类版本。
因此,我们看到Java中的动态绑定只是基于实际的对象类型而不是对象引用的声明类型来绑定方法调用(继承的方法只能在子类中被重写,因此编译器可能不确定调用哪个版本的方法)。
从以下site复制
bihw5rsg3#
运行时绑定与动态绑定或后期绑定是一样的。动态绑定基本上意味着实际调用的方法实现是在运行时确定的,而不是在编译时。这就是为什么它被称为动态绑定的原因-因为要运行的方法是在运行时选择的。
h4cxqtbf4#
一些简短的研究可以引导您找到这个http://en.wikipedia.org/wiki/Late_binding。
简短定义,以防止某些死链接:运行时绑定是一种计算机编程机制,其中对象上被调用的方法在运行时按名称查找。