Java核心 -- 多态

参考资料:

导论

在面向对象的程序设计语言中,多态是继数据抽象和继承之后的第三种基本特征。

多态也称作动态绑定、后期绑定或者运行时绑定,其作用是消除类型之间的耦合关系。 -- “编写只与基类打交道的程序”

Java是通过对方法的动态绑定来实现多态。

 

向上转型:对象既可以作为它自己本身的类型使用,也可以作为它的基类型使用,这种把对某个对象的引用视为对其基型的引用的做法被称作向上转型 -- 因为在继承树的画法上,基类是放置在上方的。

 

绑定:讲一个方法调用和一个方法实体关联起来被称作绑定。

前期绑定:在程序执行前进行绑定(如果有的话,由编译器和连接程序实现,如面向过程语言中的C语言方法调用)。

后期绑定:在运行时根据对象的类型进行绑定,后期绑定也可叫做动态绑定或运行时绑定。(即,编译器一直不知道对象的类型,但是方法调用机制能找到正确的方法体,并加以调用)

Java中除了static方法和final方法(private方法属于final方法)之外,其他所有的方法都是后期绑定。

(声明为final的方法,一方面可以防止其他人覆盖该方法,另一方面,可以有效的对该方法“关闭”动态绑定,即可以告诉编译器不需要对其进行动态绑定,这样,编译器就可以为final方法调用生成更有效的代码,以提升程序的运行性能)

 

陷阱:“覆盖”私有方法

// 主类People, 定义了say()方法
package cycle;

public class People {

    public void say(){
        System.out.println("People");
    }

    public static void main(String[] s){
        People people = new Chinese();
        people.say();
    }
}

// Chinese类继承自People,并且覆盖父类的say()方法
package cycle;

public class Chinese extends People {
    @Override
    public void say() {
        System.out.println("Chinese");
    }
}

输出结果:Chinese
分析结果:多态中,动态绑定的子类实例中的覆盖的方法

//------------------------------------------------------------------------------//
// 将Person主类中的say方法改为私有方法,不允许被子类继承
package cycle;

public class People {

    private void say(){
        System.out.println("People");
    }

    public static void main(String[] s){
        People people = new Chinese();
        people.say();
    }
}

// Chinese子类中的say就只是自己定义的一个普通方法,跟父类中的同名方法没任何关系
package cycle;

public class Chinese extends People {

    public void say() {
        System.out.println("Chinese");
    }
}

输出结果:People
分析结果:people对象虽然引用的是一个Chinese类对象,但是调用的是基类中的方法

 

构造器和多态

类的构造器实际上是static方法,只不过该static声明是隐式的。而只有普通的方法调用才可以是多态的,final方法或static方法无法实现多态。

父类的构造器总是在子类的构造过程中被调用,而且按照继承层次逐渐向上链接,以使每个基类的构造器都能得到调用。

这样做的意义是:

    构造器具有一项特殊任务:检查对象是否被正确的构造。由于子类的构造器只能访问它自己的成员,不能访问基类中的成员(基类成员通常是private类型)。只有基类的构造器才具有恰当的知识和权限来对自己的元素进行初始化。因此必须令所有构造器都得到调用,否则就不可能正确构造完整对象。这也正是编译器为什么要强调每个子类部分都必须调用构造器的原因,在子类的构造器主体中,如果没有明确指定调用某个基类构造器,它就会“默默”地调用默认构造器,如果不存在默认构造器,编译器就会报错(若某个类没有构造器,编译器会自动合成一个默认构造器)

// 父类Person,显示定义了构造器
package cycle;

public class People {

    // 父类构造器
    People (){
        System.out.println("People constructor is running");
    }
}


// 子类Chinese,通过new关键字创建新对象
package cycle;

public class Chinese extends People {

    Chinese(){
        System.out.println("Chinese constructor is running");
    }

    public static void main(String[] s){
        Chinese chinese = new Chinese();
    }
}

输出结果:
People constructor is running
Chinese constructor is running

分析结果:Chinese子类构造器中虽然没有显式调用父类构造器,但是父类构造器还是会默默先执行

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值