一、课程大纲介绍
Java继承和多态;
多态概述,认识什么是多态;
多态基础,基于继承关系的类型复用和扩展;
设计时多态、运行时多态。
二、继承的应用
2.1 什么是多态
程序运行过程中,对象角色的切换、
程序运行过程中,对象行为的扩展
2.2 继承基本语法和使用场景
多态基础:继承
继承:面向对象特征
继承基本语法结构
创建父类Father:
package seven1;
/**
*父类
*/
public class Father{
public Integer regNo;//创建属性
public String name;//创建属性
public String gender;//创建属性
public Integer age;//创建属性
public String job;//创建属性
public void woring(){//创建working方法
System.out.println(this.name + "在工作中。。。"); //打印结果
}
}
创建子类Son继承父类Father:
package seven1;
/**
*
* 子类:当前类型
*
*/
public class Son extends Father{
public void playGanme(){
System.out.println(this.name + "在游戏中。。。。");//打印结果
}
public static void main(String[] args){
Son son = new Son();//创建son对象
//操作属性
son.name = "李白";
//操作方法
son.woring();//继承
son.playGanme();//自有
}
}
继承关系的应用:医疗项目-实体类的父类
创建父类SystemUser:
package seven2;
/**
* 系统用户:父类
* @author 32856
*
*/
public class SystemUser {
public String username; //账号
public String password; //密码
public String name; //姓名
public String gender; //性别
public Integer age; //年龄
public String regNo; //身份证号码
public String phone; //手机
public String email; //邮箱
public String address; //地址
public SystemUser() {}
public SystemUser(String username,String passeword,String name) {
this.username = username;
this.password = password;
this.name = name;
}
}
分别创建三个子类Manager、Doctor、Nurse继承父类SystemUser:
package seven2;
/**
* 医护人员
* @author 32856
*
*/
public class Manager extends SystemUser {//子类Manager继承父类SystemUser
//部门
public String department;
}
package seven2;
/**
* 医师
* @author 32856
*
*/
public class Doctor extends SystemUser {//子类Doctor继承父类SystemUser
public String department;//部门
public String offices;//科室
}
package seven2;
/**
* 医护人员
*@author 32856
*
*/
public class Nurse extends SystemUser{
//部门
public String department;
}
子类继承父类的特征和行为,使得子类具有父类的各种属性和方法。或子类从父类继承方法,使得子类具有父类相同的行为。
特点:在继承关系中,父类更通用、子类更具体。父类具有更一般的特征和行为,而子类除了具有父类的特征和行为,还具有一些自己特殊的特征和行为。
三、final和super关键字
3.1 final关键字
多态基础:继承
继承:基于类型的控制
final关键字:最终的类型
package seven3;
import java.util.Date;
/**
* 医疗项目中的采购清单
* 采购方/联系方式/邮箱/传真/地址
* 提供方/联系方式/邮箱/传真/地址
* 采购编号/采购类型/采购单位/采购数量/采购单位/总计金额/备注/注意事项1~n
*
*
*/
public final class Purchase {
public String demandName;//采购方
public String demandPhone;//联系方式
public String demandEmail;//邮箱
public String demandFax;//传真
public String demandAddress;//地址
public String supplyName;//提供方
public String supplyPhone;//联系方式
public String supplyEmail;//邮箱
public String supplyFax;//传真
public String supplyAddress;//地址
public Integer purchaseId;//采购单编号
public String purchaseType;//采购类型【枚举】
public String purchaseBrand;//采购规格
public String purchaseUnits;//采购单位
public String purchasePrice;//采购单价
public Date purchaseDeal;//交易时间
public Double purchaseTotal;//总结金额
public String purchaseRemark1;//注意事项
public String purchaseRemark2;//注意事项
public String purchaseRemark3;//注意事项
public String purchaseRemark4;//注意事项
public String purchaseRemark5;//注意事项
}
继承关系的限制:医疗项目-物品清单
1)在java中不允许多重继承,一个子类只能继承一个父类,不能继承多个父类;
2)java中允许多层继承;
3)在继承中子类不能访问父类中的私有成员,只能继承公共操作。但是私有成员可以通过公共方法得到访问
3.2 super关键字
由于子类不能继承父类的构造方法,因此,如果要调用父类的构造方法,可以使用 super 关键字。super 可以用来访问父类的构造方法、普通方法和属性。
继承:单继承,突破访问限制
Java中,单继承的优势
创建父类Users:
package seven4;
public class Users {//创建类
public int id;//创建属性
public String name;//创建属性
public int age;//创建属性
public String gender;//创建属性
public boolean equals(Object obj){//创建equals方法
if(!(obj instanceof Users)){//判断obj是否与Usesrs相等
return false;
}
Users user = (Users)obj;//强制转换
return this.age >= user.age;//判断年龄并且返回
}
}
创建Doctor子类继承父类Users:
package seven4;
/**
* 医师类型
* @author 32856
*
*/
public class Doctor extends Users{//创建类并继承
public String job;//创建属性
public int level;//创建属性
public boolean equals(Object obj){//创建方法
if(!(obj instanceof Doctor)){//判断
return false;
}
Doctor dt = (Doctor)obj;//判断
if(this.level > dt.level){//判断
return true;
}else if(this.level < dt.level){//判断
return false;
}else {
//扩展父类中的对象比较方法
return super.equals(obj);
}
}
}
四、方法重载与重写
4.1 方法重载和方法重写
继承:方法重载和方法重写
方法的重写 (Overriding)和重载 (Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。
(1)方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载 (Overloading)。
(2)方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写 (Overriding)。
(3)方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
方法重载:设计时多态,医疗项目科室领取设备记录
package seven5;
/**
* 设备服务类型
* @author 32856
*
*/
public class DeviceService {
/**
*
* 医师领取设备
* 领取到的设备
*/
public String getDevic(){
return "医师领取的设备";
}
/**
* 医护领取设备
* @param notes 领取记录
* @return 返回领取到的设备
*
*/
public String getDevice(String notes){
return "医护领取的设备";
}
/**
* 病人领取的设备
* @param offices 治疗科室
* @param notes 领取记录
* @return 返回领取到的设备
*/
public String getDevice(String offices, String notes){
return "病人领取到的设备";
}
public static void main(String[] args){
//创建设备服务对象
DeviceService ds = new DeviceService();
//领取设备
String res = ds.getDevic();//医师领取设备
System.out.println(res);//打印结果
String res2 = ds.getDevice(res);//调用方法
System.out.println(res2);//打印结果
String res3 = ds.getDevice("骨科","固定带");//调用方法
System.out.println(res3);//打印结果
}
}
结果
每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。最常用的地方就是构造器的重载。
重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。
方法重写:运行时多态,医疗项目业务受理接口开发
package seven6;
/**
* 医院的类型
* @author 32856
*
*/
public class Hospital {//创建类
/**
* 挂号的操作
* @param patient 病人
* @param dept 科室
*/
public void register(Patient patient, Department dept){//创建方法
System.out.println("开始挂号到对应的科室:" + dept.name);//打印结果
dept.treatment(patient);
}
public static void main(String[] args){//主方法
//创建医院对象
Hospital hs = new Hospital();
//骨科
Orthopaedics op = new Orthopaedics();
//外科
Surgery sg = new Surgery();
//病人
Patient patient = new Patient();
//挂号
hs.register(patient, sg);
}
}
class Patient {///创建类
public int id;//编号
public String name;//姓名
public String gender;//性别
public int age;//年龄
public float health;//健康状态
}
class Department{//创建类
public int id;//编号
public String name;//名称
public String intro;//介绍
public void treatment(Patient patient ){
System.out.println(this.name + "接收病人开始治疗");
}
}
class Orthopaedics extends Department {//创建类并继承
public void treatment(Patient patient){
System.out.println(this.name + "骨科接收到病人,开始给病人进行治疗。。。。");
}
}
class Surgery extends Department {
public void treaetment(Patient patient){
System.out.println(this.name + "外科接收到病人,准备给病人手术,,,,,");
}
}
结果
五、接口和抽象类
5.1 抽象类和抽象方法
继承:抽象类基本概念
抽象方法必须用abstract关键字进行修饰。如果一个类含有抽象方法,则称这个类为抽象类,抽象类必须在类前用abstract关键字修饰。因为抽象类中含有无具体实现的方法,所以不能用抽象类创建对象。
基本语法:抽象类的意义及实现
抽象方法:抽象类中的逻辑体现(抽象方法只有声明,而没有具体的实现)
package seven7;
/**
* 继承语法中 抽象语法的讲解
* @author 32856
*
*/
public class InheritSytax {
/**
*
*驱动器类型
*类型使用abstract声明; 抽象类
*使用过程中不能被实例化
*
*/
abstract static class Device {
//方法使用abstract声明; 抽象方法 子类继承父类时必须重写的方法
public abstract void working();
//展示硬盘信息
public void showInformation() {
System.out.println("这是一个机械硬盘。。。");
}
}
static class DeviceSystem extends Device{
@Override
public void working() {
// TODO Auto-generated method stub
System.out.println("系统盘正在工作。。。。");
}
}
static class DeviceBackup extends Device {
@Override
public void working() {
// TODO Auto-generated method stub
System.out.println("备份盘正在工作中。。。。");
}
}
public static void main(String[] args) {
// //父类实例化测试:抽象类型不能实例化
// Device device = new Device();
//子类实例化
DeviceSystem ds = new DeviceSystem();
ds.working(); //直接调用重写的方法完成具体业务处理
DeviceBackup db = new DeviceBackup();
ds.working(); //直接调用重写的方法完成具体业务处理
}
}
结果
5.2 抽象类银行存款
继承:抽象类应用操作(包含抽象方法的类称为抽象类)
1)抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public。
2)抽象类不能用来创建对象;
3)如果一个类继承于一个抽象类,则子类必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。
在其他方面,抽象类和普通的类并没有区别。
银行项目:存款流程(柜台存款、ATM存款)
package seven8;
/**
* 银行类型
* @author 32856
*
*/
public class Bank {
/**
*
*
* 业务类
*
*/
static abstract class Service {
/**
* 存款的方法
* money 存款金额
* @return 返回存款收据
*/
public abstract String depostit(double money);
}
static class CashDesk extends Service {
@Override
public String depostit(double money) {
// TODO Auto-generated method stub
System.out.println("柜台存款流程");
return "柜台存款收据";
}
}
static class ATM extends Service {
@Override
public String depostit(double money) {
// TODO Auto-generated method stub
System.out.println("ATM存款");
return "ATM存款小票";
}
}
public static void main(String[] args) {
//创建渠道对象
Service service = new Bank.CashDesk();//柜台对象
Service service2 = new Bank.ATM();//ATM机
//存款:入口
int money = 0;
service.depostit(money+100);
service2.depostit(money+200);
}
}
结果
5.3 接口基本语法操作
接口:抽象类再次抽象(接口中可以含有变量和方法,接口中的方法必须都是抽象方法)
基本语法:接口的意义和基本语法
接口中的属性和方法
package seven9;
/**
*
* @author 32856
* 接口声明使用interface关键字,文件后缀依然是.java
*编译后的字节码文件,依然是.class文件
*接口的名称:通常会使用大写字母I开头,表面这就是接口
*
*接口的属性,默认修饰: public static final
*接口方法:默认修饰:public abstract
*jdk7-版本,接口中只允许存在抽象方法
*
*接口的使用方式:
* 一个接口一个继承另一个接口[单继承机制]
* 一类型(可实例化)可以实现多个接口[多实现机制]
*jdk8以后的版本:静态方法
*提供所有的实现类使用的一种公共方法,访问公共数据
*接口中的静态方法主要被接口名称调用
*静态方法:不能实现类继承,,不能被子接口继承
*
*jdk8以后的版本:默认方法
*提供给所有的实现类的一种特殊的方法,提供了一种默认的处理方式
*用于独立的基础功能的实现
*默认的方法可以被子接口基础,可以被实现类基础和重写
*默认方法只能通过实例化对象进行调用执行
*
*/
public interface IDataType {
//属性
String TyPE = "JSON";
public static final String TYPE2 = "JSON";
//方法
String format_msg(String msg);
public abstract String format_msg2(String msg);
static String getTypes() {
return IDataType.TyPE;
}
default String transfer_msg(String msg){
String res = this.format_msg(msg);
System.out.println("数据开始传输,,,");
return "数据传输结果";
}
public static void main(String[] arg){
String res = IDataType.getTypes();//静态方法
System.out.println(res);
JsonData jd = new JsonData();
jd.transfer_msg("hello tom!");//默认方法
String res2 = jd.format_msg("hello jerry");//调用普通方法
System.out.println(res2);
}
}
class JsonData implements IDataType{
@Override
public String format_msg(String msg) {
// TODO Auto-generated method stub
return "json 类型的数据 序列化操作";
}
@Override
public String format_msg2(String msg) {
// TODO Auto-generated method stub
return null;
}
}
结果
5.4 接口的应用
接口是一种极度抽象的类型,它比抽象类更加“抽象”,并且一般情况下不在接口中定义变量。
接口: 接口即规范
package seven10;
/**
* 接口应用测试
* @author 32856
*
*/
public class Produce {
static interface IDataType{
/**
*
* 简单数据约束接口
*/
String transfer();
}
static class JsonData implements IDataType{
@Override
public String transfer() {
// TODO Auto-generated method stub
System.out.println("传输JSON格式的数据");
return this.prepareData();
}
public String prepareData() {
return "JSON格式的数据";
}
}
static class XmlData implements IDataType {
@Override
public String transfer() {
// TODO Auto-generated method stub
System.out.println("准备传输XML格式的数据");
return this.prepareData();
}
public String prepareData() {
return "XML格式的数据";
}
}
static class Consumer {
public String getData(IDataType dt){
System.out.println("客户端调用接口,获取数据");
return dt.transfer();
}
}
public static void main(String[] args){
//数据提供端
IDataType dt = new JsonData();
IDataType dt2 = new XmlData();
//数据调用端
Consumer consumer = new Consumer();
String res = consumer.getData(dt2);
System.out.println(res);
}
}
结果
标记接口:数据特征的定位
package seven11;
/**
* 标记接口 测试代码
* @author 32856
*
*/
public class DataApp {
/**
* 标记接口:一旦一个类型被当前接口标记
* 这个类型在进行数据传输时,就需要进行特殊的处理
*/
static interface IDataFormat {}
/**
*
* 数据传输的方法
* @param obj 要传输的数据
* @return 传输的结果
*/
public String transfer(Object obj){
if(obj instanceof IDataFormat) {
System.out.println("复杂数据,需要进行序列化处理和类型转换");
}
System.out.println("数据监测完成,数据开始传输。。。。");
System.out.println("数据传书完成");
return "ok";
}
static class Address{
public int id;//编号
public String nation;//国家
public String province;//省份
public String city;//市区
}
static class Person implements IDataFormat{
public int id;//编号
public String name;//姓名
public String gender;//性别
public int age;//年龄
public Address address;//地址
}
public static void main(String[] arg){
//数据传输对象
DataApp da = new DataApp();
//准备数据
Address addr = new Address();
Person person = new Person();
//数据传输
da.transfer("hello");
da.transfer(12);
da.transfer(addr);
da.transfer(person);
}
}
结果哦
六、多态
6.1 多态概述
对象行为的转换,方法重写实现的操作;对象角色的转换,接口多实现的操作。
(多态就是同一个接口,使用不同的实例而执行不同操作)
6.2 多态操作案例
多态应用
商品秒杀系统:设计是多态的实现
商品秒杀系统:运行时多态的实现
package seven12;
/**
*
* 运行时多态设计
*
*/
public class Shopping2 {
/**
* 秒杀的方法
* @param name 秒杀的商品名称
* @param device 终端设备信息
*/
public void seckill(String name, Device device){
System.out.println("正在秒杀商品:" + name);
System.out.println("记录秒杀信息");
device.record(name);
}
public static void main(String[] arg){
Shopping2 shopping = new Shopping2();//商城
//PC端
Device dc = new PC();
//PC端发起秒杀
shopping.seckill("玩家国度", dc);
//移动
Device dc2 = new Phone();
//移动端发起秒杀
shopping.seckill("飞行堡垒", dc2);
}
}
abstract class Device{
public abstract void record(String name);
}
class Phone extends Device{
@Override
public void record(String name) {
// TODO Auto-generated method stub
System.out.println("移动端发起的秒杀:商品名称" + name );
}
}
class PC extends Device {
@Override
public void record(String name) {
// TODO Auto-generated method stub
System.out.println("PC端发起的秒杀:商品名称:" + name);
}
}
jieguoo