2014-12-23 118 views
0

我很难理解java中的动态绑定和继承。 继承人的代码liitle位:静态和动态绑定的概念

printer.print(person);         // Printer is printing a person, which says: I am a Person 
    printer.print(specialPerson);       // Printer is printing a special person, which says: I am a SpecialPerson 
    printer.print((Person)specialPerson);     // Printer is printing a person, which says: I am a SpecialPerson 

    System.out.println(person);        // I am a Person 
    System.out.println(specialPerson);      // I am a SpecialPerson 
    System.out.println((Person)specialPerson);    // I am a SpecialPerson 
    System.out.println(((Object)specialPerson).toString()); // I am a SpecialPerson 

SpecialPerson是一个子类的人在这里。这两个类都会覆盖toString方法。另外还有一个班级打印机,它有2种人员和专人对象的方法。我了解前三行:它调用打印机类并执行匹配类型的方法。第三行将对象动态地转换为人物对象。但是我不明白第6行:为什么对象的转换不改变被调用的方法。它不是由动态类型调用,而是静态类型?

+0

因为specialperson仍然是SpecialPerson,所以方法保持不变 – JClassic

+0

我是否正确:当我说第6行的转换操作符“改变”静态(类型),但是因为覆盖使用动态绑定,被调用的方法保持不变? – newbie

回答

0

如果方法是在超级对象上声明的,你可以在没有编译错误的情况下调用它,这是早期绑定/静态多态性。哪个方法将被执行取决于对象的动态类型是什么,这是迟绑定/动态多态性。

因此,例如:

public class Super { 
    public void foo(){}; 
} 

public class Sub extends Super { 
    @Override 
    public void foo(){ 
     System.out.println("sub"); 
    } 

    public void bar(){}; 
} 


Super s1 = new Super(); 
Super s2 = new Sub(); 
Sub s3 = new Sub(); 


s1.foo(); //prints nothing 
s2.foo(); // prints "sub" 
s3.foo(); // prinss "sub" 
s2.bar(); // won't compile even though s2 is really a Sub object 
0

Java中的所有覆盖的方法是虚拟方法如上所述here。这与其他语言(如C++)不同,您需要使用虚拟关键字来获取此行为。

维基百科:

虚函数都解决了 '晚'。如果所讨论的函数在基类中是“虚拟的”,那么无论指针或引用的声明类型如何,都会根据所引用对象的实际类型调用派生类最多的类的实现。如果它不是'虚拟',则该方法被解析为'提前',并且根据所声明的指针或引用的类型来选择所调用的函数。

由于在这种情况下只有虚拟方法,因此根据所引用对象的实际类型调用该函数 - 将它转换为某个基类对象无关紧要。