JAVA多态,动态绑定

1、多态的作用

在我们写继承时,对同一基类写继承,不同的子类可能需要重写不同的实现方法。
我们在调用这些方法时,因为这些方法所位于的类不同,又会写很多重载的代码,很不利于后期的维护修改。
这时就用到了我们的多态,举个例子比较一下:

public class Test {
    public static void main(String[] args) {
        funn(new Father());
        funn(new Child1());
        funn(new Child2());
    }
    static void funnn(Father p){  //多态的特性:可以根据父类去引用子类。
        p.fun();
    }
//    省去下面的重载代码:
//    static void funnn(Child1 p){
//        p.fun();
//    }
//    static void funnn(Child2 p){
//        p.fun();
//    }
}

class Father{
    public void fun(){
        System.out.println("执行Father类。");
    }
}
class Child1 extends Father{
    public void fun(){ //重写
        System.out.println("执行Child1类。");
    }
}
class Child2 extends Father{
    public void fun(){ //重写
        System.out.println("执行Child2类。");
    }
}

执行结果:
执行Father类。
执行Child1类。
执行Child2类。

这段代码使用funnn方法时,统一接受一个Father类的引用,他和他的子类都传入funnn。
这里看似错误(将一种类型赋给了另一种类型),但实际上没有问题,因为Chid继承了Father,Child就是一种Father类型。编译器认可这条语句(过程中子类对象自动向上转型)。更特别的是,,接下来对Father引用类的调用,完全是根据赋值的类来实现的。对同一引用类,有不同的子类去实现它。这就是多态所表现出来的。
多态允许将多种类型(从同一基类导出的)视为同一类型来处理,这样同一份代码就可以毫无差别的运行在不同类型之上了。
那么在这种情况下,编译器怎么知道Father 的引用指向自己还是哪个子类的对象呢,编译器其实不知道。只有在运行的时候,才能确定是哪个类。

2、方法绑定

1、什么是绑定

绑定就是方法的调用方法所属的类相关联,在调用时知道是哪个类的方法。

2、静态绑定(被privative,static,final修饰)

  • private 无法被子类继承或访问。所以该方法只能和定义该方法的类绑定在一起。
  • static 静态方法定义在静态区,访问时始终会访问自身的静态方法,,不随引用的对象而改变。
  • final 无法重写。子类的中继承的方法是调用父类的方法。
  • 这三个关键字修饰的方法叫做静态绑定(在编译时绑定)。

3、动态绑定

  • 除了静态绑定之外,其他方法都是动态绑定(后期绑定、运行时绑定)——在程序运行时根据对象的实际类型能找到其相应的方法。
    所以,多态其实是动态绑定的使用,而对于静态绑定,不能多态。

3、多态的优点

抽象类, 接口实现, 继承父类时进行方法的重写都可以使用多态。

  • 提高复用性 :多态帮助我们节省了很多相似的代码,用同一基类调用处理。
  • 可扩充,利于维护:在维护代码时,前面的代码始终是向后兼容的。出现新的子类,或修改某子类中的方法,只要方法及其参数是继承父类的,前面写的代码就都可以继续使用,不用对前面的代码做修改。

4、注意事项

1、父类引用指向的子类由于向上转型了,使用它只能访问父类中拥有的方法和属性,而对于子类中存在父类中不存在的方法,该引用是不能使用的。
2、多态是动态绑定的使用,静态绑定,不能使用多态(静态的方法是与类绑定,而不是对象)。

public class Father {
    private void p(){
        System.out.println('father');
    }
    public static void main(String[] args) {
        Father f = new Child();
        f.p(); //调用Father类中的p方法,输出father
    }
}
class Child extends Father{
    int a = 4;
    void p(){ //非重写的同名函数p。
        System.out.println('child');
    }
}

3、方法的调用是多态的,但属性不是,任何属性的操作都是由编译器解析的,运行时不会具有多态性。

public class Test {
    public static void main(String[] args) {
        Father f = new Child();
        System.out.println(f.a);   //输出3
        f.p();   //输出4
    }
}
class Father{
    int a = 3;
    void p(){
        System.out.println(a);
    }
}
class Child extends Father{
    int a = 4;
    void p(){
        System.out.println(a);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值