第四章 –– 多态的概念
1. 被private修饰的方法变失去了多态的能力,它不存在重写,即使子类有有同名方法也只能算新方法
探讨构造器和成员变量直接初始化的顺序?//TODO
using namespace std;
class Parent
{
protected:
virtual void draw() {
cout << "Parent draw" << endl;
}
public:
Parent() {
cout << "Parent 构造方法调用前 " << endl;
draw();
cout << "Parent 构造方法调用后 " << endl;
}
};
class Child : public Parent
{
public:
Child() {
cout << "Child 构造方法调用前 " << endl;
cout << "Child 构造方法调用后 " << endl;
}
protected:
virtual void draw() {
cout << "Child draw: " << a << endl;
}
private:
int a{ 10 };
};
int main(void) {
Parent * p = new Child(); // 父类指针(或者引用)指向子类对象, 多态产生
return 0;
}
java代码实现
package com.zhazha;
/**
* @author lenovo
* @version 1.0.0
* @date 2018/8/23 9:06
* @msg
**/
class Parent {
public Parent() {
System.out.println(" Parent 构造方法开始运行前....");
draw();
System.out.println(" Parent 构造方法开始运行前....");
}
public void draw() {
System.out.println(" Parent draw ... ");
}
}
class Child extends Parent {
private int a = 10;
public Child() {
System.out.println(" Child 构造方法开始运行前....");
System.out.println(" Child 构造方法开始运行后....");
}
public void draw() {
System.out.println(" Child draw ... a == " + a);
}
}
public class Demo {
public static void main(String[] args) {
Parent a = new Child();
}
}
多态的概念
一个对象的一个或多个方法在同一个类族中穿梭时所表现的不同功能, 叫多态
多态成立的三要素
(1) 继承
(2) 函数重写
(3) 赋值兼容性原则
. 多态中的成员访问特点:
package com.bangiao.多态的成员范文特点01;
/*
* 多态中的成员访问特点:
* (1) 成员变量
* 编译看左边, 运行看左边
* (2) 构造方法
* 创建子类对象的时候, 访问父类的构造方法, 对父类的数据进行初始化
* (3) 成员方法
* 编译看左边, 运行看右边
* (4) 静态方法
* 编译看左边, 运行看左边
* (静态和类相关, 算不上重写, 所以, 访问还是左边的)
* 由于成员方法存在方法重写, 所以它运行看右边
* */
class Fu
{
public int num = 100;
public void show()
{
System.out.println("show Fu");
}
}
class Zi extends Fu
{
public int num = 100;
public void show()
{
System.out.println("show Zi");
}
public void method()
{
System.out.println("method zi");
}
}
public class _Main
{
public static void main(String[] args)
{
Fu f = new Zi();
System.out.println(f.num);
// System.out.println(f.num2);
f.show();
// f.method();
}
}
--------------------------------------------------------------------------------
多态的好处
A: 提高了代码的维护性(由继承保证)
B: 提高了代码的扩展性(由多态保证)
多态的弊端
(1) 不能使用子类的特有功能
如果要使用的话, 直接强制转换成子类的引用变量
抽象类的特点:
A:抽象类和抽象方法必须用abstract关键字修饰
B:抽象类中不一定有抽象方法, 但是有抽象方法的类必须要定义为抽象类
C:抽象类不能实例化
因为它不是具体的
抽象类有构造函数, 但是不能实例化, 那它有什么用?
答: 用于子类访问父类数据的初始化
D:抽象类的之类
a:如果不想重写抽象方法, 该子类是一个抽象类
b:重写所有抽象方法, 这个时候子类是一个具体的类
抽象类想要实例化的话, 必须使用具体的子类来实现, 是多态的方式
抽象类的成员特点:
成员变量:既可以是变量, 也可以是常量
构造方法:有
用于子类访问父类数据的初始化
成员方法:既可以是抽象的, 也可是非抽象的方法
抽象类的成员方法特性:
A:抽象方法 强制要求子类做的事情
B:非抽象方法 子类继承的事情, 提高代码复用性
抽象类中的小问题
一个类如果没有抽象方法, 可不可以定义为抽象类? 如果可以, 有什么意义?
A:可以
B:不让创建对象
abstract 不能和哪些关键字共存
private 冲突
final 冲突
static 无意义
接口名+Impl
/*
* 接口的成员特点:
* 成员变量: 只能是常量, 并且是静态的
* 默认修饰符: public static final
* 建议自己手动写出
* 构造方法: 接口没有构造方法
* 但是每个类在定义的时候默认都继承了 Object
* public Zi extends Object implements Inter
* 这样的话即使接口没有构造函数的话, 也能通过Object
* 的构造方法进行初始化, 这个和抽象方法不用, 抽象方法
* 存在默认构造函数, 但是作用是相同的, 都是为了初始化字段
* 成员方法: 只能是抽象方法
* 默认修饰符是 public abstract
* 建议自己给出
*
* */
类与类, 类与接口, 接口与接口的关系
类与类:
继承关系, 只能单继承, 可以多层继承
类与接口:
实现关系, 可以单实现, 也可以多实现
可以实现在继承一个类的同时实现多个接口
接口与接口
接口与接口之间的关系是继承关系
可以单继承也可以多继承
--------------------------------------------------------------------------------
package 类与类类与接口接口与接口的关系;
/*
类与类:
继承关系, 只能单继承, 可以多层继承
类与接口:
实现关系, 可以单实现, 也可以多实现
可以实现在继承一个类的同时实现多个接口
接口与接口
接口与接口之间的关系是继承关系
可以单继承也可以多继承
*/
interface Father
{
public abstract void show();
}
interface Mother
{
public abstract void show2();
}
interface Sisther extends Father, Mother
{
}
class Son extends Object implements Father, Mother
{
public void show2()
{
// TODO Auto-generated method stub
System.out.println("show Mother Son");
}
public void show()
{
// TODO Auto-generated method stub
System.out.println("show Father Son");
}
}
public class _main
{
public static void main(String[] args)
{
Son s = new Son();
s.show();
s.show2();
}
}
--------------------------------------------------------------------------------
抽象类和接口的区别
A:成员区别
抽象类:
成员变量: 可以变量可以常量
构造方法: 有
成员方法: 可以抽象, 可以非抽象
接口:
成员变量: 只可以常量
成员方法: 只可以抽象
构造方法: 无
B:关系区别
类与类
继承, 单继承
类与接口
实现, 单实现, 多实现
接口与接口
继承, 单继承, 多继承
C:设计理念的区别
抽象类: 被继承的体现是共性关系
接口: 被实现体现的是拓展功能
何时使用接口何时使用抽象类
猫狗案例加入跳高功能代码实现
分析:
从具体到抽象
猫:
姓名, 年龄
吃饭, 睡觉
狗:
姓名, 年龄
吃饭, 睡觉
由于有共性功能, 所以我们抽取出一个父类;
动物:
姓名, 年龄
吃饭(); // 吃饭吃的不同
睡觉(){}// 睡觉是一样的
猫: 继承自动物
狗: 继承自动物
跳高的额外功能是一个新的拓展功能, 所以我们定义一个接口
接口:
跳高
部分猫: 实现跳高
部分狗: 实现跳高
实现:
从抽象到具体
--------------------------------------------------------------------------------
package 何时使用抽象何时接口;
// 定义接口
interface Jumpping {
public abstract void jump();
}
// 定义抽象类
abstract class Animal {
private String name;
private int age;
public Animal(String name, int age) {
super();
this.setName(name);
this.setAge(age);
}
public Animal() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
// 吃饭
public abstract void eat();
// 睡觉
public void sleep() {
System.out.println("睡觉觉了");
}
}
// 具体猫类
class Cat extends Animal {
public Cat() {
super();
}
public Cat(String name, int age) {
super(name, age);
}
public void eat() {
System.out.println("猫吃鱼");
}
}
// 具体狗类
class Dog extends Animal {
public Dog() {
super();
}
public Dog(String name, int age) {
super(name, age);
}
public void eat() {
System.out.println("狗吃肉");
}
}
class JumpCat extends Cat implements Jumpping {
public JumpCat() {
super();
}
public JumpCat(String name, int age) {
super(name, age);
}
public void jump() {
System.out.println("跳高猫");
}
}
class JumpDog extends Dog implements Jumpping {
public JumpDog() {
super();
}
public JumpDog(String name, int age) {
super(name, age);
}
public void jump() {
System.out.println("跳高狗");
}
}
public class 猫狗案例加入调高功能 {
public static void main(String[] args) {
JumpCat jc = new JumpCat();
jc.setName("哆啦A梦");
jc.setAge(3);
System.out.println(jc.getName() + "---" + jc.getAge());
jc.eat();
jc.sleep();
jc.jump();
System.out.println("-----------------------------------");
JumpCat jc2 = new JumpCat("加菲猫", 2);
System.out.println(jc2.getName() + "---" + jc2.getAge());
jc2.eat();
jc2.sleep();
jc2.jump();
System.out.println("-----------------------------------");
JumpDog jd = new JumpDog("小黄", 4);
System.out.println(jd.getName() + "---" + jd.getAge());
jd.eat();
jd.sleep();
jd.jump();
}
}
package 学生老师案例加入抽烟功能;
/*
* 深刻理解抽象类和接口类的作用
* 抽象类是用于共性功能, 比如所有子类都有吃饭, 但是吃的东西不同, 这个就
* 可以独立出来
* 接口类主要的功能便是功能的扩展, 扩展一个子类的某个功能
* */
interface ISmoking {
public abstract void smoke();
}
abstract class AbsPerson {
private String name;
private int age;
public AbsPerson(String name, int age) {
super();
this.setName(name);
this.setAge(age);
}
public AbsPerson() {
super();
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
abstract public void eat();
public void sleep() {
System.out.println("睡觉了");
}
}
class TeacherImpl extends AbsPerson {
public void eat() {
// TODO Auto-generated method stub
System.out.println("吃大白菜");
}
}
class StudentImpl extends AbsPerson {
public void eat() {
// TODO Auto-generated method stub
System.out.println("吃红烧肉");
}
}
class SmokeTeacher extends TeacherImpl implements ISmoking {
public void smoke() {
// TODO Auto-generated method stub
System.out.println("老师抽烟");
}
}
class SmokeStudent extends StudentImpl implements ISmoking {
public void smoke() {
// TODO Auto-generated method stub
System.out.println("学生抽烟");
}
}
public class _Main {
public static void main(String[] args) {
SmokeStudent ss = new SmokeStudent();
ss.setAge(20);
ss.setName("meimei");
ss.eat();
ss.sleep();
ss.smoke();
System.out.println("--------------------------------");
SmokeTeacher st = new SmokeTeacher();
st.setAge(30);
st.setName("laoshi");
st.eat();
st.sleep();
st.smoke();
}
}
--------------------------------------------------------------------------------
多态的分类:
A:具体类多态
B:抽象类多态
C:接口类多态
多态的转型
A:向上转型
从子到父
B:向下转型
从父到子
案例: 孔子装爹
何时使用抽象类何时使用接口?
回顾猫狗案例:
它们仅仅提供了一些基本功能, 例如: 猫钻火圈, 狗跳高等功能, 这些功能不是这些动物特有的, 而是通过后天的训练出来的, 这种额外的功能java中提供了接口表示
星级酒店案例
11星级酒店案例
* A: 根据“某五星级酒店,资金雄厚……都有自己的工作要做。”分析出,该题目中包含酒店,可以把它封装成类,多名员工)。
class 员工 {
属性:姓名
属性:工号
方法:工作
}
class 厨师 extends 员工{}
class 服务员 extends 员工{}
class 经理 extends 员工 {
属性:奖金
}
员工的类型有经理、厨师、服务员,它们有共同的属性(姓名、工号、),经理额外属性(奖金)。
根据“向酒店中,增加多名员工(其中包含1名经理,1名厨师、2名服务员)”。分析出,要创建一个酒店对象,并添加4名员工到酒店对象的员工集合中。
酒店员工集合添加新员工: 经理对象
酒店员工集合添加新员工: 厨师对象
酒店员工集合添加新员工: 服务员对象
酒店员工集合添加新员工: 服务员对象
根据“获取酒店幸运员工”。分析出,从酒店员工集合随机得到一名员工对象。
1. 从酒店员工集合长度范围内,随机产生一个随机数
2. 使用该随机数作为集合的索引,返回该索引处对应的员工对象
根据“酒店开设VIP服务,酒店的厨师与服务员可以提供VIP服务。(厨师做菜加量、服务员给顾客倒酒)”。分析出,这是要增加一个VIP的接口,接口中提供个VIP服务的方法。让厨师与服务员实现该接口。
interface VIP服务{
抽象方法:服务
}
class 厨师 extends 员工 implements VIP服务{ 重写服务方法 }
class 服务员 extends 员工 implements VIP服务{ 重写服务方法 }
B:
VIP服务
public interface VIP {
public abstract void server(); //服务
}
员工
/*
* 员工:
姓名 String
工号 String
*/
public abstract class YuanGong {
// 成员变量
private String xingMing;
private String gongHao;
// 构造方法
public YuanGong() {
super();
}
public YuanGong(String xingMing, String gongHao) {
super();
this.xingMing = xingMing;
this.gongHao = gongHao;
}
// 抽象方法
public abstract void work();
// getters与setters
public String getXingMing() {
return xingMing;
}
public void setXingMing(String xingMing) {
this.xingMing = xingMing;
}
public String getGongHao() {
return gongHao;
}
public void setGongHao(String gongHao) {
this.gongHao = gongHao;
}
}
服务员
/*
* 定义员工的子类 服务员类
*/
public class FuWuYuan extends YuanGong implements VIP {
public FuWuYuan() {
super();
}
public FuWuYuan(String xingMing, String gongHao) {
super(xingMing, gongHao);
}
public void work() {
System.out.println("亲,全身心为您服务,记得给好评哦");
}
public void server() {
System.out.println("给顾客倒酒");
}
}
经理
/*
* 经理在员工的基础上,添加了奖金成员
*/
public class JingLi extends YuanGong {
private double jiangJin;
public JingLi() {
super();
}
public JingLi(String xingMing, String gongHao, double jiangJin) {
super(xingMing, gongHao);
this.jiangJin = jiangJin;
}
public double getJiangJin() {
return jiangJin;
}
public void setJiangJin(double jiangJin) {
this.jiangJin = jiangJin;
}
public void work() {
System.out.println("哪个员工让顾客不满意,我扣谁钱");
};
}
厨师
/*
* 定义员工的子类 厨师类
*/
public class ChuShi extends YuanGong implements VIP{
public ChuShi() {
super();
}
public ChuShi(String xingMing, String gongHao) {
super(xingMing, gongHao);
}
public void work() {
System.out.println("我做饭,放心吃吧,包您满意");
}
public void server() {
System.out.println("做菜加量加料");
}
}
<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">