Java编程思想之八多态
在面向对象的程序设计语言中,多态是继数据和继承之后的第三张基本特征
多态不但能够改善代码组织结构和可读性,还能够创建可扩展的程序——即无论在项目最初创建时还是在需要添加新功能时都可以"生长"的程序。
封装通过合并特征和行为来创建新的数据类型。"实现隐藏"则通过将细节"私有化",把接口和实现分离开来。多态的作用就是消除类型之间的耦合关系。
多态方法调用允许一种类型表现出与其他相似类型之间的区别。
8.1 再论向上转型
把某个对象的引用视作对其基类的引用称为向上转型——因为再继承树中,基类是放置在上方的。
8.2 转机
基类如何知道引用指向哪个导出类?
8.2.1 方法调用绑定
将一个方法调用同一个方法主体关联起来被称作绑定。若在程序执行前进行绑定,由编译器和连接程序实现,叫做前期绑定,此为面向过程语言默认绑定方式。
后期绑定:就是在运行时,根据对象的类型进行绑定。后期绑定也叫做动态绑定或运行时绑定。
Java中除了satic方法和final方法之外,其他所有都是后期绑定。
8.2.3 可扩展性
在一个设计良好的OOP程序中,程序是可扩展的,因为可以从通用的基类继承出新的数据类型,从而新添一些功能。那些操作基类接口的方法不需要任何改动就可以应用于新类。
8.2.4 缺陷:覆盖私有方法
public class PrivateOverride {
private void f(){
System.out.println("private f()");
}
public static void main(String[] args){
PrivateOverride po=new Derived();
po.f();
}
}
class Derived extends PrivateOverride{
public void f(){
System.out.println("public f()");
}
}
只有非private方法才可以被覆盖,在导出类中,对于基类的private方法,最好采用不同的名字。
8.2.5 缺陷:域与静态方法
public class FieldAccess {
public static void main(String[] args){
Super sup=new Sub();
System.out.println("sup.feld="+sup.field+",sup.getField()="+sup.getField()+"");
//output:sup.feld=0,sup.getField()=1
Sub sub=new Sub();
System.out.println("sub.field="+sub
.field+",sub.getField()="+sub.getField()+",getSuperField="+sub.getSuperField()+"");
//output:sub.field=1,sub.getField()=1,getSuperField=0
}
}
class Super{
public int field=0;
public int getField(){
return field;
}
}
//Sub包含了两个域,自己的field和继承来的field
class Sub extends Super{
public int field=1;
public int getField(){
return field;
}
public int getSuperField(){
return super.field;
}
}
如果某个方法是静态的,它的行为就不具有多态性
public class StaticPolymorphism {
public static void main(String[] args){
StaticSuper sup=new Staticsub();
System.out.println(sup.staticGet());//output:Base staticGet()
System.out.println(sup.dynamicGet());//output:Derived dynamicGet()
}
}
class StaticSuper{
public static String staticGet(){
return "Base staticGet()";
}
public String dynamicGet(){
return "Base dynamicGet()";
}
}
class Staticsub extends StaticSuper{
public static String staticGet(){
return "Derived staticGet()";
}
public String dynamicGet(){
return "Derived dynamicGet()";
}
}
静态方法是与类,而非与单个的对象相关联
8.3 构造器和多态
构造器并不具有多态性,它们实际上是static方法,只不过该static声明是隐试的。
8.3.1 构造器的调用顺序
基类构造器总是在导出类的构造过程中被调用,而且按照继承层次逐渐向上链接,以使每个基类的构造器都能得到调用。意义:构造器具有一项特殊的任务,检查对象是否被正确的构造。导出类只能访问它自己的成员,不能访问基类中的成员(基类成员通常使private类型)。只有基类的构造器才具有恰到的知识权限来对自己的元素进行初始化。
对象调用构造器遵循以下顺序:
- 1.调用基类构造器
- 2.按声明顺序调用成员初始化方法
- 3.调用导出类构造器的主体
8.3.2 继承与清理
通过组合和继承方法来创建新类时,永远不必担心对象的清理问题,子对象通常都会留给垃圾回收器进行处理。
8.3.3 构造器内部的多态方法的行为
如果调用构造器内部的一个动态绑定方法,就要用到哪个方法的覆盖后的定义。然而,这个调用效果可能难以预测,因为被覆盖的方法在对象完全构造之前就会被调用。
public class PolyConstructors {
public static void main(String[] args){
new RoundGlyph(5);
}
}
class Glyph{
void draw(){
System.out.println("Glyph.draw()");
}
Glyph(){//2
System.out.println("Glyph() before draw()");//3
draw();//4
System.out.println("Glyph() after draw()");//6
}
}
class RoundGlyph extends Glyph{
private int radius=1;//7
RoundGlyph(int r){//1
radius=r;//8
System.out.println("RoundGlyph.RoundGlyph().radius="+radius+"");//9
}
void draw(){
System.out.println("RoundGlyph.draw(),radius="+radius+"");//5
}
}
初始化过程:
- 1.在其他任何事物发送之前,将分配对象的存储控件初始化成二进制零
- 2.调用基类构造器
- 3.按照声明顺序调用成员初始化方法
- 4.调用导出类的构造器主体
Java编程思想之八多态的更多相关文章
- 【学习笔记】JAva编程思想之多态
1.如果java的基类拥有某个已被多次重载的方法名称,那么在导出类中重新定义该方法名称并不会屏蔽在基类的任何版本.因此,无论是在该层或者他的基类中对方法进行定义,重载机制都可以正常工作. 2.使用@O ...
- 《java编程思想》多态与接口
向上转型 定义:把某个对象的引用视为对其基类类型的引用的做法被称为向上转型方法调用绑定 将一个方法调用同一个方法主体关联起来被称作绑定. 前期绑定:程序执行前进行的绑定叫做前期绑定,前期绑定也是jav ...
- (七)《Java编程思想》——多态的缺陷
1.不能“覆盖”私有方法 package chapter8; /** * 不能"覆盖"私有方法 */ public class PrivateOverride { private ...
- Java编程思想(四) —— 复用类
看了老罗罗升阳的专訪,不由自主地佩服,非常年轻,我之前以为和罗永浩一个级别的年龄.也是见过的不是初高中编程的一位大牛之中的一个,专訪之后.发现老罗也是一步一个脚印的人. 别说什么难做,做不了.你根本就 ...
- Java编程思想学习(一)----对象导论中多态的理解
1.1抽象过程 1)万物皆对象. 2)程序是对象的集合,他们通过发送消息来告知彼此所要求做的. 3)每个对象都有自己的由其他对象所构成的存储. 4)每个对象都拥有其类型. 5)某一特定类型的所有对象都 ...
- 《Java编程思想》学习笔记_多态
多态 多态指一个行为产生多种状态,针对父类类型可接收其子类类型,最终执行的状态由具体子类确定,其不同子类可呈现出不同状态.例如人[父类]都会跑步[行为],但小孩[子类]跑步.成年人[子类]跑步.运动员 ...
- 《Java编程思想》学习笔记(二)——类加载及执行顺序
<Java编程思想>学习笔记(二)--类加载及执行顺序 (这是很久之前写的,保存在印象笔记上,今天写在博客上.) 今天看Java编程思想,看到这样一道代码 //: OrderOfIniti ...
- Java编程思想重点笔记(Java开发必看)
Java编程思想重点笔记(Java开发必看) Java编程思想,Java学习必读经典,不管是初学者还是大牛都值得一读,这里总结书中的重点知识,这些知识不仅经常出现在各大知名公司的笔试面试过程中,而 ...
- java编程思想-复用类总结
今天继续读<java 编程思想>,读到了复用类一章,看到总结写的很好,现贴上来,给大家分享. 继承和组合都能从现有类型生成新类型.组合一般是将现有类型作为新类型底层实现的一部分来加以复用, ...
随机推荐
- box-shadow 模糊半径与扩展半径
关于box-shadow的基本用法参阅CSS3 box-shadow一章节. 此属性用来设置元素的阴影效果,语法结构如下: box-shadow:h-shadow v-shadow blur spre ...
- 编写可维护的JavaScript-随笔(三)
UI层的松耦合 本章提出了一个概念就是耦合 假设修改一个组件的时候需要修改很多其他的组件的话则表示组件之间存在紧耦合 如果修改一个组件而不需要修改其他组件的时候就做到了松耦合 页面是由HTML.CSS ...
- js根据json数组多个字段排序
/**数组根据数组对象中的某个属性值进行排序的方法 * 使用例子:newArray.sort(sortByArr(['number'],false)) //表示根据number属性降序排列;若第二个参 ...
- Vue学习之Webpack小结(十二)
一.nrm: nrm是专门用来管理和快速切换私人配置的registry; nrm提供了一些最常用的npm包镜像地址,能够让我们快速的切换安装包时候的服务器地址: 二.镜像: 原来 包 刚一开 ...
- js学习之堆栈内存
**栈内存** >基本数据类型值是直接存放在栈内存中的 栈内存中的变量一般都是已知大小或者有范围上限的,算作一种简单存储.而堆内存存储的对象类型数据对于大小这方面,一般都是未知的.个人认为,这也 ...
- aws centos系统磁盘扩容
growpart /dev/xvda 1 展开修改后的分区(注意是:空格 1,而非打错了) # ext3/4 1.resize2fs /dev/xvda1 将分区调整为新的卷容量 # xfs分区 2 ...
- 微信小程序引入外部组件 iView Weapp
iview Weapp组件的使用方法: 1. 下载小程序组件库 (前提是你已经有了项目目录) 你可以直接去github把iView Weapp的代码下载下来,也可以用过npm来下载. github地址 ...
- JanusGraph安装graphexp
准备:JanusGraph环境,graphexp源码,nginx 本文采用的环境:JanusGraph + cassandra + ES + GraphExp(cassandra 或者HBase作为后 ...
- Fedora 29 安装 GitBook 教程
Fedora 29 安装 GitBook 教程 本文原始地址:https://sitoi.cn/posts/53731.html 安装 nvm 安装 nvm curl -o- https://raw. ...
- 开机没有deepin启动项的解决办法
增加efi/deepin/grubx64.efi的启动项 问题描述 打开电脑,进入bios没有deepin启动项 解决办法 进入bios setup,选择boot sourquense,选择uefi, ...