Java 动态绑定/多态
class Point { int x = 0, y = 0; //父类成员Var public void move(int x,int y){ this.x += x; this.y += y; } public int getX(){ return x; } public int getY(){ return y; } } class RealPoint extends Point { float x = 0.0f ,y = 0.0f; //子类成员Var , 与父类同名,隐藏父类成员Var, 包括访问权限、类型 均以子类为准。 public void move(float x, float y){ //与继承的父类方法的重写(Override)构成重载。 this.x += x; //this指向本身的引用,this.x 代表自身类的成员Var this.y += y; } public void move(int x,int y){ //对父类方法的重写,调用自身类的重载方法(Overload)参数个数和类型不同,其余相同。 move((float)x, (float)y); } public int getX() { return (int)Math.floor(x); //Math.floor() 向下取整,直接截取小数点后小数部分。 } public int getY() { return (int)Math.floor(y); } } public class Polymorphism { public static void main(String []args) { RealPoint rp = new RealPoint(); //创建子类对象,子类引用指向子类对象 Point p = rp; //父类引用类型,指向子类对象(p 和 rp指向内存同一块区域)Casting 对象转型 rp.move(1.71828f,4.14159f); //调用子类定义的第一个方法 p.move(1,-1); //调用子类定义的第二个方法,其真正实现,由第一个方法实现。 show(p.x, p.y); //显示父类成员Var, 非静态成员变量在类加载的第二阶段已经加载好了,不会有动态绑定。 show(rp.x, rp.y); //显示子类成员Var show(p.getX(),p.getY()); //调用子类getX() getY(),子类方法返回子类成员Var,成员方法(有继承,有父类引用指向子类对象,有重写)会实现动态绑定,
//调用实际指向的对象的方法,即调用RealPoint中的getX(),getY();
show(rp.getX(),rp.getY()); //调用子类成员方法 } public static void show(int x, int y){ System.out.println("(" + x + "," + y + ")"); } public static void show(float x ,float y) { System.out.println("(" + x + "," + y + ")"); } }
(0,0) (2.7182798,3.14159) (2,3) (2,3)
源程序如上图,动态绑定(多态) 是针对的非static 、非final的成员方法,隐藏针对的是成员变量和static 方法。(针对且只针对)
只有Override (重写) 才会进行动态绑定,隐藏(即子类声明和父类同名同类型的成员变量和static 方法,则子类实例化对象通过对象名调用成员Variable 和 static 方法,子类的相应将父类隐藏,只会显示子类的成员Var 和 static 方法)。隐藏不会进行动态绑定。
内存布局如图所示,
1、p和rp指向同一子类对象。
2、子类继承父类,即子类对象包含父类对象。
3、动态绑定:原本父类对象的move()指针指向父类Point()的方法,由于有继承、有父类引用指向子类对象、有重写,Java会执行动态绑定机制,使得源代码中p.move(1,-1)调用的为子类的move()方法。 move()由黑线改成蓝色指向的move()方法。
4、父类引用指向子类对象,只能调用子类的方法,不能得到子类的成员变量(成员Var 无动态绑定,且Casting限定了父类引用只能使用父类Obj内部的方法和变量)。即p.getX() 调用的为子类方法。 p.x 不会得到子类的成员Var , 这也就是结果第一、二的出现的原因。
5、但是父类引用指向子类对象,调用子类方法,子类方法可以对子类成员变量进行操纵,近似于(但不等同于)父类引用可以得到子类成员Var(但并非直接,而是通过子类方法,子类方法向外提供修改子类成员Var的接口). p.getX() p.getY() 而 getX() getY()返回的为子类自身成员Var。程序结果第三、四行出现的结果。