Java的继承、封装与多态
Java的继承、封装与多态
基本概念
- 面向对象OO(Object Oriented):把数据及对数据的操作方法放在一起,作为一个相互依存的整体,即对象。
- 对同类对象抽象出共性,即类。
比如人就是一个类,所有的人都有一些共同的属性,比如身高体重肺活量,还有一些特定的操作,即方法,比如吃饭,思考。但是人只是一个抽象的概念,所有具备人这个群体的属性和方法的对象都叫人,我们只能说张三这个实例化的人身高是多少,体重是多少,而不能说人这个类身高是多少。 - OOP面向对象编程:指软件开发的过程中,通过面向对象的思想进行表达和实现。
- 重构:指对程序做出一定的改变。
面向对象的特征:
封装,继承与多态。
封装
有时称为数据隐藏
将数据和和对数据的操作隐藏在一个类中,即隐藏对象的属性和实现细节,仅对外公开接口。
使用者不需要知道类的具体实现,只要知道怎么调用就可以了。
比如:
所有类的成员变量一般设置为private,如果需要访问和修改,通过getter和setter方法,优点:
1.可以改变内部实现,除了该类的方法外,不会影响其他代码。
private String firstName;
private String lastName;
public String getName(){
return firstName + "" + lastName;
}
2.setter方法可以执行错误检查,比如检查数据是否合乎规范,输入的age是否小于0,直接对域操作则没这种优势
3.可细微划分访问控制:可以只设置域访问器getter,不设置域修改器setter,让用户只能读取,而不能修改。而public既可以读取,也可以修改,可能造成数据不安全。
继承
是一种类的层次模型,从现有的类中通过extends关键字派生新类,现有的类称为父类,新类称为子类。
子类可以从它的父类那里继承方法和实例变量,并且可以重写父类的方法和增加新的方法。一般将通用的方法放到超类中,具有特殊用途的方法放到子类中。
特点:
- 不能多重继承。
- 只能继承非私有的成员变量和方法
- 当子类成员变量与父类成员变量重名时,子类覆盖父类。
- 定义为final的类不可继承,定义为final的方法不可以被重写。
多态
- 指允许不同类的对象对同一消息(即同一个方法的调用)做出响应。即同一个方法的调用,可以根据调用这个方法的对象的不同而实现不同的功能。
- 在Java核心技术第5章中定义:
实现多态的技术称为:动态绑定(dynamic binding),是指在运行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。 - 多态的作用:降低类型之间的耦合关系。
把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。
例子
- 比如:
如果我们定义
Animal animal = new Cat(); //表示我定义了一个Animal类型的引用,指向新建的Cat类型的对象
或者
Cat cat = new Cat();
如果我要改为子类Dog类,那么前者只需要修改一行代码,不需要改实例名,后者要大量改动。
Animal animal = new Dog();
- 再比如:
你可以设计一个接口:DataBaseDao
然后,每个不同的数据库,你可以编写接口的实现类,比如:SQLServerDao, MySqlDao, DB2Dao等等
当用户使用你框架的时候,他就可以用多态,实现自己的数据库连接功能:
DaoBaseDao dao = new SQLServerDao(); //针对SQLServer的接口实现,这里dao就是多态
dao.connect();
- 再比如:
现实中,关于多态的例子不胜枚举。比方说按下 F1 键这个动作,如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;如果当前在 Word 下弹出的就是 Word 帮助;在 Windows 下弹出的就是 Windows 帮助和支持。同一个事件发生在不同的对象上会产生不同的结果。
但注意:父类类型的引用可以调用父类中定义的所有属性和方法,而对于子类中定义而父类中没有的方法,它是无可奈何的;比如子类中增加的方法,父类引用无法调用。
多态存在的三个必要条件
一、要有继承;
二、要有重写;
三、父类引用指向子类对象。
多态的好处:
1.可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。
2.可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。
3.接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。
4.简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。
Java中多态的实现方式:
- 方法的重载(overload):重载是指同一个类中有多个同名的方法,但这些方法有不同的参数,因此在编译期就可以确定到底调用哪个方法,它是一种编译时多态。即一个类中的方法多态性。
- 方法的覆盖(即重写)(override):子类可以覆盖父类的方法,即同样的方法会在子类和父类中有不同的表现形式。在Java语言中,父类引用可以指向父类对象或者子类对象,接口引用可以指向其实现类的实例对象。 而程序调用的方法在运行期才动态绑定(绑定指的是将一个方法调用和一个方法主体连接到一起),即:在运行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。(注意此时父类引用只是指向子类对象,真正运行的还是子类对象,即优先从实际运行的对象的方法表中找对应的方法签名(方法名+参数列表称为方法签名),如果找不到,才回到相应的父类方法表中找调用方法的方法签名),由于运行时才能确定调用哪个方法,因此称方法覆盖的多态为运行时多态。
在《深入理解Java虚拟机》的P248页,
对方法的重载称为:静态分派(根据静态类型)
package org.fenixsoft.polymorphic;
/**
* 方法静态分派演示
* @author zzm
*/
public class StaticDispatch {
static abstract class Human {
}
static class Man extends Human {
}
static class Woman extends Human {
}
public void sayHello(Human guy) {
System.out.println("hello,guy!");
}
public void sayHello(Man guy) {
System.out.println("hello,gentleman!");
}
public void sayHello(Woman guy) {
System.out.println("hello,lady!");
}
public static void main(String[] args) {
Human man = new Man();
Human woman = new Woman();
StaticDispatch sr = new StaticDispatch();
sr.sayHello(man);
sr.sayHello(woman);
}
}
运行结果:
hello,guy!
hello,guy!
注意这里的静态类型指static类型,但其实不是static类型结果也一样,只不过将内部类写为static的可以实现和外部类相同的调用方式,比如:
public class StaticDispatch {
abstract class Human {
}
class Man extends Human {
}
class Woman extends Human {
}
public void sayHello(Human guy) {
System.out.println("hello,guy!");
}
public void sayHello(Man guy) {
System.out.println("hello,gentleman!");
}
public void sayHello(Woman guy) {
System.out.println("hello,lady!");
}
public static void main(String[] args) {
StaticDispatch staticDispatch = new StaticDispatch();
Human man = staticDispatch.new Man();
Human woman = staticDispatch.new Woman();
StaticDispatch sr = new StaticDispatch();
sr.sayHello(man);
sr.sayHello(woman);
}
}
代码中刻意地定义了两个静态类型相同但实际类型不同的变量,但虚拟机(准确地说是编译器)在重载时是通过参数的静态类型而不是实际类型作为判定依据的。并且静态类型是编译期可知的,因此,在编译阶段,Javac编译器会根据参数的静态类型决定使用哪个重载版本,所以选择了sayHello(Human)作为调用目标,并把这个方法的符号引用写到main()方法里的两条invokevirtual指令的参数中。
对方法的覆盖称为:动态分派(根据实际类型)
例子:
class Base {
public int i = 1;
public Base() {
g();
}
public void f() {
System.out.println("Base f");
}
public void g() {
System.out.println("Base g");
}
}
public class Derived extends Base {
public int i = 2;
public void f() {
System.out.println("Derived f");
}
public void g() {
System.out.println("Derived g");
}
public static void main(String args[]) {
Base b = new Derived();
b.f();
System.out.println(b.i);
}
}
输出:
Derived g
Derived f
1
上面的例子说明了:只有类中的方法才有多态的概念,类中成员变量没有多态的概念。类中成员变量的值取决于所定义变量的类型,这是在编译期间确定的。
面向接口编程
参考:http://www.cnblogs.com/leoo2sk/archive/2008/04/10/1146447.html
面向接口编程和面向对象编程是什么关系
首先,面向接口编程和面向对象编程并不是平级的,它并不是比面向对象编程更先进的一种独立的编程思想,而是附属于面向对象思想体系,属于其一部分。或者说,它是面向对象编程体系中的思想精髓之一。
接口的本质
- 接口是一组规则的集合,它规定了实现本接口的类或接口必须拥有的一组规则。体现了自然界“如果你是……则必须能……”的理念。
- 接口是在一定粒度视图上同类事物的抽象表示。比如我们说我和猴子不属于一类,分别继承Person接口和Monkey接口,但对动物学家,我们却继承同一接口:Animal接口。
面向接口编程的本质
在系统分析和架构中,分清层次和依赖关系,每个层次不是直接向其上层提供服务(即不是直接实例化在上层中),而是通过定义一组接口,仅向上层暴露其接口功能,上层对于下层仅仅是接口依赖,而不依赖具体类。
好处:
- 对系统灵活性大有好处。当下层需要改变时,只要接口及接口功能不变,则上层不用做任何修改。甚至可以在不改动上层代码时将下层整个替换掉。
- 不同部件或层次的开发人员可以并行开工,就像造硬盘的不用等造CPU的,也不用等造显示器的,只要接口一致,设计合理,完全可以并行进行开发,从而提高效率。
抽象类与接口
如果单从具体代码来看,对这两个概念很容易模糊,甚至觉得接口就是多余的,因为单从具体功能来看,除多重继承外(C#,Java中),抽象类似乎完全能取代接口。
区别
- 使用动机。使用抽象类是为了代码的复用(可以理解为代码和表示的共享机制),而使用接口的动机是为了实现多态性。
- 抽象类和它的子类之间应该是一般和具体的关系,而接口仅仅是它的子类应该实现的一组规则。
Java的继承、封装与多态的更多相关文章
- [Objective-C] 004_继承封装与多态
继承 面向对象编程 (OOP) 语言的一个主要功能就是"继承".继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展.通过继承创建的 ...
- java类的封装 继承 多态
1.猜数字小游戏 package cn.jiemoxiaodi_02; import java.util.Scanner; /** * 猜数字小游戏 * * @author huli * */ pub ...
- 九、Java基础---------面向对象封装、继承、多态
封装 1.1 基本概念 封装(encapsulation)是面向对象三大特征之一,它是指将对象的状态信心隐藏在对象的内部,不允许外部直接进行访问,而是通过该类提供的方法来实现对内部信息的操作和访问. ...
- java类的封装、继承、多态
一.封装(encapsulation) 封装性就是把类(对象)的属性和行为结合成一个独立的相同单位,并尽可能隐蔽类(对象)的内部细节,对外形成一个边界,只保留有限的对外接口使之与外部发生联系.封装的特 ...
- Java三大特性(封装,继承,多态)
Java中有三大特性,分别是封装继承多态,其理念十分抽象,并且是层层深入式的. 一.封装 概念:封装,即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别:将抽象得到的数据 ...
- 第32节:Java中-构造函数,静态方法,继承,封装,多态,包
构造函数实例 class Cat{ // 设置私有的属性 name private String name; // 设置name的方法 public void setName(String Name) ...
- 【Java基本功】一文了解Java中继承、封装、多态的细节
本节主要介绍Java面向对象三大特性:继承 封装 多态,以及其中的原理. 本文会结合虚拟机对引用和对象的不同处理来介绍三大特性的原理. 继承 Java中的继承只能单继承,但是可以通过内部类继承其他类来 ...
- Java中的继承、封装、多态的理解
Java中的继承.封装.多态 继承的理解: 1.继承是面向对象的三大特征之一,也是实现代码复用的重要手段.Java的继承具有单继承的特点,每个子类只有一个直接父类. 2.Java的继承通过extend ...
- 浅析Java三大特性封装、继承、多态,及作业分析
前言 本次博客衔接上次博客,作为这一阶段Java学习的分析.上一篇博客着重介绍了Java的OO编程思维,面向对象与面向过程的区别.本篇博客重心在Java的三大技术特性,附带作业分析. Java三大特性 ...
随机推荐
- Java第九周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次PTA作业题集异常 1.常用异常 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己 ...
- Smrty模版总结(转)
转自:http://www.cppblog.com/amazon/archive/2011/11/21/160638.html 前提:1. 部署smarty模板目录:2. 编写Smarty类的子类,定 ...
- FTP下载时连接正常获取不到数据
今天项目中要下载快钱的对账单,快钱对账单文件的FTP服务器是Unix系统,connectServer方法中已连接成功,reply code:220. 但是问题是download方法中的ftpClien ...
- Java NIO vs IO
NIO :http://tutorials.jenkov.com/java-nio/index.html IO:http://tutorials.jenkov.com/java-io/index.ht ...
- birt 集成到现有的web应用中
我们已经有了一个Javaweb应用,现在要实现对报表的集成 我的应用是这个样子的 说明: 1) 这里使用的是birt4.4版本的, 下载birt-runtime-4.4.zip(在官方下载),然 ...
- Saltstack批量编译部署nginx(多模块)
最近一直在研究saltstack的同步文件和批量执行命令,随着架构的变大,批量部署的需求也变得明显起来了,我需要用一条命令就部署好nginx和tomcat,并且符合我所有的环境需求,可以直接投入生产环 ...
- #翻译#原文来自Database.System.Concepts(6th.Edition.2010)2.6Relational Operations,原文作者Abraham Silberschaz , Henry F. Korth , S. Sudarshan
2.6关系操作 所有的过程关系查询语言都提供一组操作,这些操作可以应用于单个关系或一对关系.这些操作具有良好的和期望的属性,它们的结果总是一个单一的关系.这个属性允许一个以模块化的方式组合其中的几个操 ...
- 基于Quartz实现简单的定时发送邮件
一.什么是Quartz Quartz 是一个轻量级任务调度框架,只需要做些简单的配置就可以使用:它可以支持持久化的任务存储,即使是任务中断或服务重启后,仍可以继续运行.Quartz既可以做为独立的应用 ...
- vue-chat项目之重构与体验优化
前言 vue-chat 也就是我的几个月之前写的一个基于vue的实时聊天项目,到目前为止已经快满400star了,注册量也已经超过了1700+,消息量达2000+,由于一直在实习,没有时间对它频繁地更 ...
- python采用 多进程/多线程/协程 写爬虫以及性能对比,牛逼的分分钟就将一个网站爬下来!
首先我们来了解下python中的进程,线程以及协程! 从计算机硬件角度: 计算机的核心是CPU,承担了所有的计算任务.一个CPU,在一个时间切片里只能运行一个程序. 从操作系统的角度: 进程和线程,都 ...