JAVASE 面向对象06-多态

一、多态

1.多态概述

某一个事物,在不同时刻表现出来的不同状态。

举例:
猫可以是猫的类型。猫 m = new 猫();
同时猫也是动物的一种,也可以把猫称为动物。
动物 d= new 猫();

​ 猫,即可以叫猫,也可以叫动物

注:new xx赋值时,永远从右边向左边说就错不了

在举一个例子:水在不同时刻的状态 . 水 ( 液体, 固体, 气态)

多态: 同一个对象,在不同时刻体现出来的不同状态

2.多态的前提

A. 要有继承关系
B. 要有方法重写
​      如果没有方法重写,使用意义就不大了
​     动物  d1 = new  狗();
​      d1.show()
​     动物  d2 = new  猫();
​      d2.show();
​    如上面的案例,如果没有重写,调用的方法一样,就没有了意义 

C. 要有父类的引用指向子类
​     父   f  = new  子();  //这就是多态

3.多态的案例

class Father{
    public void show(){
        System.out.println("fu");
    }
}
class Son extends Father{
    public void show(){
        System.out.println("zi");
    }
     public void method(){
        System.out.println("zi mothod");
    }
}
public class Demo1 {
    public static void main(String[] args) {
        // 父类引用指向子类
        Father father = new Son();
    }
}

4.多态中的成员访问特点

类的成员: 成员变量,成员方法,构造方法

多态中的成员访问特点:

A: 成员变量(重点)
​ 编译看左边, 运行看左边

​ B: 构造方法
​ 子类的构造都会默认访问父类构造,对父类的数据进行初始化

C: 成员方法(重点)
​ 编译看左边, 运行看右边;

​ 为什么呢?
​ 因为成员方法有重写(覆盖)

​ 结论: 由于成员方法存在方法重写,所以它运行看右边

D: 静态方法(静态与类相关的,其实算不上重写,所以访问的还是左边的)

​ 编译看左边,运行也看左边.

5.多态的优缺点

1.多态的缺点

   父类不能用子类的特有方法

   可是,我就想用子类的特有方法,行不行

​    行

​    怎么用?

   A:    创建子类对象调用方法即可.  (可以但是很多时候不合理.而且太点内存了)  Son son = new Son();

​	B:    把父类的用强制转换为子类的引用.....(向下转型)

对象间的转型问题:

向上转型:

​    Father f = new Son();

向下转型

​     Son son = (Son) f;    // 注意: 类型必须要兼容

2.多态的优点

A. 提高了代码的维护性(继承保证)

B. 提高了代码的扩展性(多态来保证的)

6.多态的理解

class  张三爹{
    int age = 46;
    public void teach(){
     System.out.println("法律");
    }
}

class 张三 extends 张三爹{
    int age = 22;
    public void teach(){
        System.out.println("音乐");
    }
    public void paly(){
        System.out.println("玩王者");
    }
}
public class Demo2 {
    public static void main(String[] args) {
        // 张三爹  名气很高   很多人请他讲课
        // 有一天  张三爹出去讲课了   来了一个人,想邀请张三爹, 给的费用很高
        // 但是不在,怎么办? 张三心动
        // 伪装成爹    穿上他爹的衣服,带上眼镜, 贴上胡子    外表看已经是他爹的样子
        张三爹  fu = new 张三();
        System.out.println(fu.age);
        fu.teach();
        // 下课了,做你自己,脱下你爹装备
        张三 son = (张三)fu;
        son.paly();

  }
}

内存图来理解多态

向下转型的内存图
向下转型的内存图

二、抽象

1.抽象的概述

回想前面我们的猫狗案例提取出了一个动物类。并且我们在前面也创建过了动物对象,其实这是不对的。
为什么呢?

因为,我说动物,你知道我说的是什么动物吗?只有看到了具体的动物,你才知道,这是什么动物。

所以说,
动物本身并不是一个具体的事物,而是一个抽象的事物。
只有真正的猫,狗才是具体的动物。

同理,我们也可以推想,不同的动物吃的东西应该是不一样的,
所以,我们不应该在动物类中给出具体体现,而是应该给出一个声明即可。

在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法;该类必须定义为抽象类

2.抽象类的特点

  1. 抽象类与抽象 方法用abstract 关键字

  2. 抽象类中不一定有抽象方法,但是有抽象方法的类,一定要定义为抽象类

  3. 抽象类不能实例化

    因为它不是具体的类,所以不能实例化

    抽象类有没有构造方法呢? 有

    构造方法方法的作用是什么? 用于子类访问父类的时候进行数据初始化

  4. 抽象类的子类

    1. 抽象类的子类也是一个抽象类, 它可以不用去实现抽象方法
    2. 如果它的子类不是抽象类(具体类),必须重写所有的抽象方法

有了具体的类以后,抽象类可以能过多态来实现实例化

​ 抽象类 fu = new 具体类()

3.抽象类的成员特点

成员变量: 即可以变量,也可以是常量

构造方法: 有
​ 作用是: 用于子类访问父类的时候进行数据初始化

成员方法:可以是抽象方法, 也可以是非抽象方法( 也可以称为具体方法,或普通方法)

抽象类中的成员方法的特点:

  1. 是抽象方法 强制要求子类必须做的事情
  2. 非抽象方法 子类继承父类的事情( 提高代码复用性 )

4.抽象类案例

猫狗案例

分析: 从具体到抽象

​ 猫类:

​ 成员变量: 姓名,年龄

​ 成员方法: 吃饭( 吃鱼),睡觉(趴着)

​ 狗类:

​ 成员变量: 姓名,年龄

​ 成员方法: 吃饭( 吃肉),睡觉(站着)

因为发现上面的多个类中,有共同属性和方法,所以我们提取了一个单独的类,放共同属性和方法,这个类称为 动物  => (继承)

但是,它们吃饭,和睡觉的方法是不一样的, 所以,把吃饭,睡觉写成抽象方法

因为方法是抽象 的,所以类必须是抽象 类

实现: 从抽象到具体

 动物类

	成员变量 姓名,年龄
	构造方法: 有参构造,无参
	抽象 方法:  吃饭,睡觉

狗类

	继承动物类
	构造方法: 有参构造,无参
	重写抽象方法

猫

	继承动物类
	构造方法: 有参构造,无参
	重写抽象方法

5.抽象类中的问题

一个类中如果没有抽象方法,可以不定义为抽象类?

​ 可以, 为了不让它被实例化

abstract  不能和哪些关键字共存

​    private  冲突    错误信息: 非法的修饰符组合: abstract和private

​    final   冲突                    错误信息: 非法的修饰符组合: abstract和final

​    static  冲突                     错误信息:非法的修饰符组合: abstract和static

接口

Object类

包装类

StringBuilder , StringBuffer类

三、接口

狗它能钻火圈,可以握手

为了某一个事物,实现额外的功能,就可以使用接口来定义, 然后谁实现了这个接口,谁就可以使用这个功能

1.接口特点

  1. 用Interface 关键字表示(定义)

    interface 接口名{ }

  2. 类去实现接口用 implements

    class 类名 implements 接口名{ }

  3. 接口不能实例化

    接口不能直接实例化,但是可以通过多态来进行实例化

  4. 接口的的子类

    a: 可以是抽象类,但是意义不大

    b: 可以用具体的类,要重写接口中的所有方法(推荐)

    由些可见:

    多类的分类:

      1. 具体类的多态( 比较少 )
      1. 抽象类的多态( 常用)
      1. 接口的多态(最常用)
    

2.接口成员特点

  • 成员变量: 只能是常量 默认修饰符: public static final

​ 建议: 自己手动给出

构造方法: 没有构造方法,因为接口主要是功能的扩展,没有具体的存在

  • 成员方法: 只能是抽象方法,默认修饰符: public abstract

​ 建议: 自己手动给出

注: 接口实现类: 一般用 接口名+ Impl 命名

3.类与类,类与接口,接口与接口

  • 类与类:

​ 继承关系,只能单继承,不能多继承,但是可以多层继承

  • 类与接口

​ 实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时,实现多个接口

  • 接口与接口

​ 继承关系,可以单继承,也可以多继承

4.抽象类与接口的区别

  • 成员区别:

    抽象类: 成员变量: 可以变量,也可以是常量

    构造方法 有

    成员方法 抽象 方法, 也可以是非抽象 方法

    接口 : 成员变量:常量

    构造方法 无
    成员方法 抽象方法 (jdk8 支持 default 方法 和 static 方法,jkd9 支持 private 方法,供 default 方法调用 )

  • 关系区别:

    类与类:

    继承关系,只能单继承,不能多继承,但是可以多层继承

    类与接口:

    实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时,实现多个接口

    接口与接口:

    继承关系,可以单继承,也可以多继承

设计理念区别

    抽象类:  is a   关系  (共性功能)   
    接口:   like a 关系   (扩展功能)

5.接口支持的方法

jdk8之前,接口中的方法,只能定义抽象方法

jdk8 支持方法,default 方法和static方法 . 为什么?

  • 默认方法的使用场景包括:
  1. 为接口添加新的方法,而不会破坏已有代码的兼容性。
  2. 允许接口提供默认实现,从而减少实现类的工作量。
  • 静态方法的使用场景包括:

    提供与接口相关的工具方法,这些方法可以在接口中定义为静态方法。

jdk9 支持private 方法,主要是给default 方法

作用

默认方法和静态方法的作用是为了提供更加灵活和方便的接口设计。

四、方法的参数和返回值

写一个方法时,思考:它的返回值类型

1.参数类型

  • 类名作为参数(需要传递的是类的实例对象)

  • 抽象类作为参数(需要传递的是, 它的具体要类的实例对象)

  • 口作为参数(需要传递的是, 它的实现类的实例对象)

2.返回值

  • 类名作为返回值类型: 返回对应类的对象

  • 抽象类作为返回值类型: 返回抽象类的具体类的对象

  • 接口作为返回值类型: 接口实现类的对象

3.权限修饰符

  权限修饰符        本类     同一个包下(子类和无关类)   不同包子类    不同包的无关类
   
   private         Y             
   
   默认             Y           Y
   
   protected       Y           Y                     Y
   
   public          Y           Y                     Y             Y

五、常见的修饰特点

修饰符:
      权限修饰符    private  默认的   protected  public
      状态修饰符    static   final
      抽象修饰符    abstract
      
类
      权限修饰符    默认的    public
      状态修饰符    final
      抽象修饰符    abstract
      (以上public用的最多)
      
成员变量
      权限修饰符    private  默认的   protected  public
      状态修饰符    static   final
       (用的最多的是private)
       
成员方法
      权限修饰符    private  默认的   protected  public
      状态修饰符    static   final
      抽象修饰符    abstract
      (用的最多的public)
      
构造方法
      权限修饰符    private  默认的   protected  public
     (用的最多的public)
     
 组成规则
        组成变量   public static final
        成员方法   public static
                  public abstarct
                  public final      
     
      

测试:

1.编码

南方人和北方人

Person

​ eat

北方人

​ eat

​ 研究

南方人

​ eat

​ 经商

测试类

创建一个南方人

向上转型

转回来 南方人

  • 13
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值