面向对象-多态(引入抽象类和接口)

多态

多态的概述

什么是多态

字面上讲,多态就是某一个事物,在不同时刻表现出来的不同状态。
当我们多个子类继承一个父类时,使父类引用指向子类对象(父类 对象名=new 子类()),就是多态的形式。

多态的前提
  1. 要有继承关系。
  2. 要有方法重写。 其实没有也是可以的,但是如果没有这个就没有意义。
    子类需要对父类方法进行重写,多态就是为了通过调取父类类型的对象既可完成子类特有功能,若子类无方法重写,我们直接调取子类对象即可,失去了多态的意义。
  3. 要有父类引用指向子类对象。父 f = new 子();

多态的优势与劣势

  • 优势
    比如我们需要对几种不同的动物饮食习惯进行描述,那么这些不同的动物有公共的属性与功能,为了同时体现出他们独有的功能属性,继承是必不可少的。
  1. 现在我们定义猫、狗和老虎(三个类继承于动物父类):
    在这里插入图片描述
  2. 在不使用多态时,我们添加Set类来调用eat:
    在这里插入图片描述
  3. 测试这三种动物的饮食习惯
    在这里插入图片描述
  4. 但是如果现在出现了一个新的物种猫狗兽CatDog,我们需要新增加一个子类Catdog:
    在这里插入图片描述
    但是在增加子类的同时我们的Set类中也需要添加对CatDog类中eat方法的调用,如果在增添大量的子类,我们会发现Set类需要不断的修改:
    在这里插入图片描述
    会发现过程会变得十分的繁琐,是代码毫无扩展性。所以我们引入多态的形式
    在这里插入图片描述
    在这里插入图片描述
    这样就变得简单了许多,并且增添新的子类是无需修改Set类。提高了代码的扩展性,降低了类之间的耦合性。
  • 弊端
    多态无法调用子类特有的方法
    当我们用父类引用创建子类对象时,通过父类调用子类特有方法会出现类型转换异常:
    在这里插入图片描述
    在这里插入图片描述
    这时我们需要向下转型(多态就是向上转型),将父引用转成他所指向的那个子类型:
    在这里插入图片描述

多态中的成员访问特点

我们创建一个父类一个子类,子类继承与父类,其中都有各自的成员变量,构造方法,静态方法,并且子类重写了父类的成员方法,我们通过多态的形式创建子类对象。
在这里插入图片描述

构造方法

创建子类对象的时候,会访问父类的构造方法,对父类的数据进行初始化。
在这里插入图片描述
在这里插入图片描述

成员变量
  • 多态的形式去访问成员变量,访问的还是父类的成员变量
  • 编译看左边,运行看左边
    在这里插入图片描述
    在这里插入图片描述
成员方法
  • 多态的形式去调用方法时,调用的是子类改写后的成员方法。
  • 编译看左边,运行看右边
    在这里插入图片描述
    在这里插入图片描述
静态方法
  • 引为静态方法内存中存在于方法区,可通过类名直接调用,所以静态方法不算重写,通过子类对象调用的依然是父类的静态方法,想调用子类的静态方法直接通过子类名访问。
  • 编译看左边,运行看左边
    在这里插入图片描述
    在这里插入图片描述

抽象类

回想前面我们的猫狗案例,提取出了一个动物类。并且我们也创建过了动物对象,其实这是不对的。
因为我们给动物定义具体的功能属性本来就是不合理的,动物是一个抽象的事物,并不是一个具体的事物,所以我们不应该给动物定义具体的属性和功能,之给出一个声明即可,具体的功能应该在具体的猫狗等等中具体定义。

抽象类概述

什么是抽象类
  • 在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类。
抽象类特点
  • 我们依然拿描述动物和猫举例
  1. 抽象类和抽象方法必须用abstract关键字修饰
    抽象类格式: abstract class 类名 {}
    抽象方法格式: public abstract void eat();
    在这里插入图片描述
  2. 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
    在这里插入图片描述
  3. 当一个类,继承了一个抽象类,那么这个抽象类中的所有抽象方法,子类必须重写
    在这里插入图片描述
  4. 抽象类中可以有构造方法,抽象类不能进行实例化,那么要构造方法有什么作用呢?
    用于子类访问父类数据时的初始化
    抽象类不能直接实例化那么,抽象类如何实例化呢?
    按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
    在这里插入图片描述
  5. 抽象类的子类:要么是抽象类,要么重写抽象类中的所有抽象方法
    在这里插入图片描述

抽象类的成员特点

  1. :成员变量:既可以是变量,也可以是常量。
  2. 构造方法:有
    用于子类访问父类数据的初始化。
  3. 成员方法:既可以是抽象的,也可以是非抽象的。
  • 抽象类的成员方法有什么特性呢?
  1. 抽象方法:强制要求子类做的事情。
  2. 非抽象方法:由子类继承,提高代码复用性。

接口

继续回想我们的猫狗案例,当我们已经定义过了猫和够的属性与功能,有一天突然发现我们的猫学会了抓老鼠,狗学会了看门,我们去在子类中添加这些功能会十分麻烦,也不合适,因为不是所有的猫和狗都学会了额外的本领。
所以,为了体现事物功能的扩展性,Java中就提供了接口来定义这些额外功能,并不给出具体实现,将来哪些猫狗具备了这种特性,只需要这部分猫狗把这些额外功能实现即可。
在这里插入图片描述

接口的特点

  1. 接口用关键字interface表示 格式: interface 接口名 {}
    接口中定义的是抽象方法
    在这里插入图片描述
  2. 类实现接口用implements表示 格式:class 类名 implements 接口名 {}
    实现接口的子类必须对接口中方法进行重写
    在这里插入图片描述
  3. 接口不能实例化那么,接口如何实例化呢?
    按照多态的方式来实例化。
    在这里插入图片描述
  4. 接口的子类:
  • 可以是抽象类。但是意义不大。
  • 可以是具体类。要重写接口中的所有抽象方法。

接口的成员特点

  1. 成员变量:只能是常量,并且是静态的。
    默认修饰符:public static final
    建议:自己手动给出。
    在这里插入图片描述
  2. 构造方法:接口没有构造方法。
  3. 成员方法:只能是抽象方法。
    默认修饰符:public abstract
    建议:自己手动给出。
    在这里插入图片描述
  • JDK1.8之后在接口中提供了用default修饰的方法,可以给出功能的具体实现,子类可以继承下去用
    在这里插入图片描述
    在这里插入图片描述

类、抽象类、 接口之间的关系

类与接口的关系

  1. 类与类:
    继承关系,只能单继承,可以多层继承。
  2. 类与接口:
    实现关系,可以单实现,也可以多实现。
    并且还可以在继承一个类的同时实现多个接口。
    这说明接口的引入弥补了继承关系中无法多继承的缺陷
    在这里插入图片描述
  3. 接口与接口:
    继承关系,可以单继承,也可以多继承。
    在这里插入图片描述

抽象类和接口的区别

成员区别
  • 抽象类
    成员变量:可以变量,也可以常量
    构造方法:有
    成员方法:可以抽象,也可以非抽象
  • 接口:
    成员变量:只可以常量
    成员方法:只可以抽象
关系区别
  • 类与类
    继承,单继承
  • 类与接口
    实现,单实现,多实现
  • 接口与接口
    继承,单继承,多继承
设计理念区别
  • 抽象类
    被继承体现的是:”is a”的关系。 抽象类中定义的是该继承体系的共性功能。
  • 接口
    被实现体现的是:”like a”的关系。 接口中定义的是该继承体系的扩展功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值