面向对象之多态

本文详细介绍了面向对象编程中的多态概念,包括其前提、演示、注意事项及优缺点。同时,讲解了多态成员访问的特点,如成员变量、成员方法和静态方法的访问规则。此外,探讨了类与类、类与接口、接口与接口之间的关系,并通过实例展示了抽象类和接口的使用,以及它们在代码扩展性和维护性方面的重要性。最后,通过实例展示了多态在实际场景中的应用,如模拟学校授课功能和汽车制造过程。
摘要由CSDN通过智能技术生成

一. 多态

  1. 定义

    • 一个事物的多种形态
  2. 多态的前提

    • 要有父子关系(决定了可以使用多态)
    • 要有父类引用指向子类对象
    • 要有方法重写(决定了代码有没有实际意义)
  3. 演示

    public class Father {
    	public void method(){
    		System.out.println("父类method方法");
    	}
    }
    //子类继承父类
    public class Son extends Father {
      	//重写父类的方法
    	public void method(){
    		System.out.println("子类的method方法");
    	}
    }
    public static void main(String[] args) {
    	//父类类型的变量引用子类类型的实例对象
    	Father father = new Son();
      	father.method();
    }
    
  4. 注意事项

    • 可以做哪些工作看父类类型
    • 实际做工作的看子类对象
    • 优点: 提高了代码的扩展性, 复用性,维护性, 可以当作形参,用来接收任意类型的子类对象
    • 缺点: 不能使用子类的特有属性和方法
  5. 演示

    • 学校有授课功能, 但是需要聘请老师讲课, 编程模拟
    public class School {
    
    	public void teach(Teacher teacher){
    		teacher.teach();
    	}
    }
    
    public class Teacher {
    	public void teach(){
    		System.out.println("老师上课");
    	}
    }
    
    public class MusicTeacher extends Teacher{
    	public void teach() {
    		System.out.println("优美的歌声从教室中飘出");
    	}
    }
    
    public class MathTeacher extends Teacher{
    	public void teach() {
    		System.out.println("认真的讲解着每一个运算步骤");
    	}
    }
    
    public static void main(String[] args) {
    	School school = new School();
    	//调用学校的授课功能, 传递一个音乐老师过去
    	school.teach(new MusicTeacher());
    	//调用学校的授课功能, 传递一个数学老师过去
    	school.teach(new MathTeacher());
    }
    
  6. 测试题

    • 动物都有吃饭的功能, 但是小狗吃的是狗粮, 小猫吃的猫粮,当我们将小猫小狗体貌特征遮盖住的时候, 如何判定吃东西的是小猫还是小狗? 编程模拟

二. 多态成员访问的特点

  1. 成员变量

    • 编译看左边(父类) , 运行看左边(父类) (静态绑定)
    • 一般中情况使用极少, 成员变量一般都是私有化的
    public class Father {
    	
    	String name = "小红";
    }
    public class Son extends Father {
    	
    	String name = "小明";
    	
    }
    public static void main(String[] args) {
    	Father father = new Son();
    	
    	String str = father.name;
    	System.out.println(str); //小红
    }
    
  2. 成员方法

    • 编译看左边(父类), 运行看右边(子类), 动态绑定
    • 子类中如果对父类中的方法进行了重写, 父类中的方法无论如何都无法被访问, 这也是java动态绑定的结果
    • 动态绑定会选择最优执行方法, 只要子类重写了父类的方法, 无论在什么地方调用, 都会先找子类
    public class Father {
    	
    	public void method(){
    		System.out.println("父类method方法");
    	}
    }
    
    public class Son extends Father {
    	
    	public void method(){
    		System.out.println("子类method方法");
    	}
    }
    public static void main(String[] args) {
    	Father father = new Son();
    	
    	father.method();//子类method方法
    }
    
  3. 静态方法

    • 编译看左边(父类),运行看左边(父类)
    public class Father {
    	
    	public static void method(){
    		System.out.println("父类method方法");
    	}
    }
    public class Son extends Father {
    	
    	public static void method(){
    		System.out.println("子类method方法");
    	}
    }
    public static void main(String[] args) {
    	Father father = new Son();
    	
    	father.method();//父类method方法
    	//Father.method();
    }
    
  4. 测试题

    • 判断结果
    package com.qianfeng.duotai;
    class Fu{
    	public void show() {
    		System.out.println("fu show");
    	}
    }
    
    class Zi extends Fu {
    	public void show() {
    		System.out.println("zi show");
    	}
    
    	public void method() {
    		System.out.println("zi method");
    	}
    }
    
    class TestDemo {
    	public static void main(String[] args) {
    		Fu f = new Zi();
    		f.method();
    		f.show();
    	}
    }
    
    • 判断结果
    class A {
    	public void show() {
    		show2();
    	}
    	public void show2() {
    		System.out.println("我");
    	}
    }
    class B extends A {
    	public void show2() {
    		System.out.println("爱");
    	}
    }
    class C extends B {
    	public void show() {
    		super.show();
    	}
    	public void show2() {
    		System.out.println("你");
    	}
    }
    public static void main(String[] args) {
    	A a = new B();
    	a.show();
    	
    	B b = new C();
    	b.show();
    }
    

三. 多态转型

  1. 向上转型

    • 将子类对象看作是父类类型, 也就是我们平时使用的多态的形式
    • 这种情况下, 无法调用子类特有的功能
  2. 向下转型

    • 将父类引用指向的子类对象再转回子类类型

    • 这种转型是有危险的, 因为是强制性的, 一旦转向的类型跟这个对象不匹配, 就会报错java.lang.ClassCastException (类型转换异常, 属于运行时异常)

      public static void main(String[] args) {
      	Father f = new Son();
      	//转回子类类型
      	Son son = f; //
      }
      

四. final关键字

  1. 定义

    • final 表示最终的, 无法被修改的
  2. final修饰的特点

    • 修饰类, 类不能被继承
    • 修饰变量, 变量就变成了常量, 只能被赋值一次(初始化的时候赋值 )
    • 修饰方法, 方法不能被重写
  3. final 修饰局部变量

    • 基本数据类型 , 是值不能被改变
    • 引用数据类型, 是地址值不能被改变, 对象中的属性可以改变
    • final可以修饰形参
  4. final 修饰成员变量的初始化时机

    • 必须手动赋值

    • 对象初始化完毕之前

    • 类初始化完成前(静态)

      public class Demo {
      	
      	final String name = "小红";
      	{
      		//name = "小红";
      	}
      	public Demo(){
      		//name = "小红";
      	}
      }
      
  5. 测试题

    • 判断结果
    public class Demo {
    	
    	final String name ="小红";
    	
    	public void method(){
    		name = "小明";
    		System.out.println(name);
    	}
    	//final修饰变量的时候,只能赋一次值
    	public void method2(final String name){
    		System.out.println(name);
            
    		final int age;
    		age = 10;
    		System.out.println(age);
    	}
    }
    
    public static void main(String[] args) {
    	Demo demo = new Demo();
    	demo.method();
    	demo.method2("小红");
    }
    

五. 抽象类

  1. 定义

    • 抽象类没有具体的代码实现, 只是规定了方法的基本属性, 然后由子类去实现具体的代码, 抽象类主要是为了定义规则而存在的
  2. 特点

    • 抽象类和抽象方法必须用abstract 关键字修饰
      • abstract class 类名{}
      • abstract 返回追类型 方法名();
    • 抽象类不一定有抽象方法, 有抽象方法的类一定是抽象类或者接口
    • 抽象类不能实例化, 必须由子类继承并重写抽象方法来实例化
    • 抽象类的子类
      • 要么是抽象类
      • 要么重写抽象类中的所有抽象方法(普通类)
  3. 演示

    • 公司的员工必须都要有打卡和工作的功能, 所有员工都是使用指纹打卡, 但是工作的方式因岗位的不同而不同
    public abstract class Employee {
    	
    	public void sign(){
    		System.out.println("指纹打卡");
    	}
    	
    	public abstract void work();
    }
    
    public class Hr extends Employee{
    
    	@Override
    	public void work() {
    		System.out.println("招聘人才");	
    	}
    	
    }
    
    public class Coder extends Employee{
    
    	@Override
    	public void work() {
    		System.out.println("努力的敲代码");
    	}
    
    }
    
  4. 测试题

    • 汽车工厂的已经将车的主体完成,汽车已经可以开动了, 后期需要根据不同的用途安装不同的部件, 货车需要安装货箱, 用来拉货, 客车需要安装座椅,用来拉人
  5. 抽象类成员方法的特点

    • 抽象方法 , 强制要求子类做的事情
    • 非抽象方法, 子类继承的方法, 提高代码的复用性
  6. 优点

    • 强制子类实现父类的方法功能
    • 提高代码的扩展性, 便于后期的维护
    • 形成一套规范(重点)
  7. 测试题

    • 具体事物:猫,狗
    • 共性:姓名,年龄,吃饭 (抽象类中成员变量的使用和普通类是一样的)
    • 猫的特性 : 抓老鼠
    • 狗的特性 : 看家

六. 接口

  1. 定义

    • 接口其实就是抽象类的升级版, 接口里面都是抽象方法
    • 从狭义上将来说, 接口就是指java 中的interface
    • 从广义上的角度讲对外提供规则的都是接口
    • 接口就是一套标准的规范(规则)
  2. 特点

    • 接口用关键字interface表示
      • interface 接口名{ }
      • 接口中方法上的abstract关键字可以省略
    • 类实现接口用implements表示
      • class类名 implements 接口名{ }
    • 接口不能实例化
      • 接口按照多态的方法实例化
    • 接口的子类
      • 可以是接口,使用extends来继承
      • 可以是抽象类, 但意义不大
      • 可以是实体类, 要重写接口中的所有抽象方法( 主要使用 )
    • 接口中的成员变量必须是 公共的 静态的 最终的 , 也就是常量
      • public ,static , final 关键字可以省略 (建议省略)
    • 接口可以继承接口
  3. 演示

    //接口1
    public interface MyInterface {
    	//定义了静态常量 static final 可以省略
    	static final String NAME = "小红";
    	//定义了抽象方法
    	public void method();
    	//定义了抽象方法
    	public void method2();
    }
    //接口2 继承了接口1
    public interface MyInterface2 extends MyInterface {
    	//定义了抽象方法
    	public void method2();
    }
    //定义实现类实现接口
    public class MyInterfaceSon implements MyInterface2{
    	//重写抽象方法
    	@Override
    	public void method() {
    		
    		System.out.println("重写method抽象方法");
    	}
    	//重写抽象方法
    	@Override
    	public void method2() {
    		
    		System.out.println("重写method2抽象方法");
    	}
    }
    
  4. 测试题

    • 定义老师接口 讲课方法, 辅导作业方法
    • 定义实现的子类, 不同老师不同的讲课方式和辅导作业的方式

七. 类 , 接口之间的关系

  1. 类与类
    • 继承关系, 只能单继承 ,不能多继承 ,但是可以多层继承
    • 多层继承: 子类继承父类,父类继承祖父类
    • 如果多个父类出现相同的方法,无法区别
  2. 类与接口
    • 实现关系,可以单实现, 也可以多实现, 在继承类的同时,可以多实现
    • 多个接口中出现了名称和参数列表相同的方法, 但是返回值不同, 会报错
  3. 接口与接口
    • 继承关系 ,可以单继承, 也可以多继承
    • 如果多个父类中出现了相同的,子类用谁的都可以

总结:

  1. 多态

    一个事物的多种形态

    一个子类对象,可以被看做是父类类型

    父类引用指向子类对象(父类类型的变量可以存储子类类型的对象)

  2. 多态的优缺点

    提高了代码的扩展性 , 复用性和维护性

    子类的特有方法和属性无法使用了

  3. 多态下,对象成员访问的特点

    成员变量 : 编译看左边, 运行看左边 (基本无用, 成员变量一般私有化)

    成员方法 : 编译看左边, 运行看右边 (主要使用方式)

    静态成员 : 编译看左边, 运行看左边 (基本无用,静态使用类名调用)

  4. 转型

    子类对象被父类变量引用 : 向上转型

    父类引用再赋值给子类变量 : 向下转型 (有风险,强转)

  5. final关键字

    final修饰类, 类不能被继承

    final修饰方法, 方法不能被重写

    final修饰变量 , 变量只能赋值一次

    final修饰成员变量, 必须在初始化完成前手动给成员变量赋值

  6. 抽象类

    一个特殊的无法实例化的类, 内部可以写抽象方法

    抽象方法 :

    ​ 只有方法的结构,没有具体的代码,使用 abstract 关键字标识

    意义 :

    ​ 定义规则, 强制子类重写

    特点 :

    ​ 可以有抽象方法,也可以有非抽象方法

    ​ 抽象类无法实例化(创建对象)

    ​ 子类可以是抽象类,可以是非抽象类

  7. 接口

    一种特殊的抽象类, 里面全是抽象方法 , 而且省略的很多的关键字

    定义接口的关键字是 interface , 普通类实现接口 implements

    接口的方法省略 public abstract

    接口中的成员变量成略了 public static final

  8. 类,接口之间的关系

    类和类 : 继承关系, 只能但继承,可以多层继承

    接口和接口 : 继承关系, 可以多继承

    类和接口 : 实现关系, 可以多实现

作业

  1. 第一题

    • 一档选秀节目, 设计了一个平台供参与者展示才艺, 不同的参与者有不同的才艺. 使用多态编程模拟
  2. 第二题

    • 学生都有学习和做作业的能力 , 但是学习的方式不同, 使用抽象类的方法模拟编程
  3. 第三题

    • 创建一个乐器接口 Instrument, 定义演奏方法play, 定义两个实现类 钢琴 Piano, 小提琴 Violin ,分别实现乐器接口,并做出不同的演奏
  4. 第四题

    • 国家规定, 汽车必须能点火, 能开动, 国家将文件发送到汽车厂商的手中, 厂商生产的汽车必须符合要求, 可以有特性功能, 编程模拟
  5. 扩展题

    class A{
    	public String show(D obj){ //D obj = new D();
    		return ("A and D");	
    
    	}
    	public String show(A obj){ //A obj = new D();
    
    		return ("A abd A");
    	}
    }
    class B extends A{
    	public String show(B obj){
    
    		return ("B and B");
    	}
    	public String show(A obj){
    		
    		return ("B and A");
    	}
    }
    class C extends B{ }
    class D extends B{ }
    
    问题:以下输出结果是什么?
    A a1 = new A();
    A a2 = new B();
    B b = new B();
    C c = new C();
    D d = new D();
    System.out.println(a1.show(b)); ① A abd A
    System.out.println(a1.show(c)); ② A abd A
    System.out.println(a1.show(d)); ③ A and D
    System.out.println(a2.show(b)); ④ B and A
    System.out.println(a2.show(c)); ⑤ B and A
    System.out.println(a2.show(d)); ⑥ A and D
    System.out.println(b.show(b));  ⑦ B and B
    System.out.println(b.show(c));  ⑧ B and B
    System.out.println(b.show(d));  ⑨ A and D
    //能执行哪些方法,看变量的类型
    //如果有多态,那么实际执行那个方法看子类
    //如果有多个方法可行,找最合适的,也就是最接近的
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值