多态、引用类型转换、抽象类、接口
一、多态
1. 引用多态
父类引用可以指向本类对象
父类引用也可以指向子类对象
2. 方法多态
创建本类对象时,调用的方法为本类方法
创建子类对象时,调用方法为子类重写的方法或继承的方法
****************************************************************************************************************************************
来一段代码:
父类Animal:
子类Rabbit:
main函数:
可以看到父类引用只可以指向本类对象或者子类对象,而不能用子类引用指向父类对象
给类的代码写入方法
父类Animal的eat()
子类Rabbit的eat()重写
再写一个子类Cat继承Animal,写一个父类没有的函数catchMouse()
main函数:
可以看到,由于父类Animal中没有catchMouse()方法,所以不能用父类对象obj3来调用子类的方法
执行结果:
************************************************************************************************************************
二、引用类型转换
*************************************************************************************************************************
在刚才编写的Animal、Rabbit、Cat类代码的基础上写main函数
代码中的第二种类型转换,编译器认为存在风险,会编译报错。
应该写为:
这两个强制类型转换,也是存在风险的。原因是:
这个引用animal,指向一个Rabbit对象,没有办法转换成Cat类型。但编译器不报错,运行时出错。
编译时是按Cat类型编译的,但运行时,由于真正开辟的内存空间是Rabbit类型的,发现两个类型不匹配,所以不能进行强制类型转换。
通过instanceof运算符避免类型转换的安全性问题。可以判断一个引用是否是某个类型或者某个类型的子类型,返回一个布尔值
运行时报错:
用instanceof这样写就可以:
运行结果:
****************************************************************************************************************************************************
三、抽象类
1. 语法定义:
抽象类前使用abstract关键字修饰,则该类为抽象类。
2. 应用场景:
(1)在某些情况下,某个父类只是知道其子类应该包含怎样的方法,但无法准确知道这些子类如何实现这些方法。
(2)从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为子类的模板,从而避免了子类设计的随意性。
3. 作用:
限制规定子类必须实现某些方法,但不关注实现细节。
4. 使用规则:
(1)abstract定义抽象类
(2)abstract定义抽象方法,只有声明,不需要实现
(3)包含抽象方法的类是抽象类
(4)抽象类中可以包含普通的方法,也可以没有抽象方法
(5)抽象类不能直接创建,可以定义引用变量
*******************************************************************************************************************************
抽象类的代码:
先写一个抽象类Telephone,点击abstract
写两个抽象方法
第一个子类Cellphone,表示以前的手机。继承抽象类Telephone,自动生成两个方法等待我们写具体的实现过程
两个方法都输出语句
再写第二个子类Smartphone,表示智能手机。同样继承Telephone,写上方法的具体实现
写一个测试类带main函数
执行结果:
******************************************************************************************************************************
四、接口
1. 接口概念
类是一种具体实现体,而接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部数据,也不关心这些类里方法的实现细节,它只规定这些类里必须提供某些方法。
2. 接口定义
和类定义不同,定义接口不再使用class关键字,而是使用interface关键字。
3. 接口语法(1)
(2)接口在定义时有abstract关键字,如果没有显式写abstract,系统也会自动加上
(3)接口可以继承多个父接口,且可以继承父接口也可以不继承
4. 接口定义
接口中的属性是常量,即使定义时不添加public static final修饰符,系统也会自动加上。
接口中的方法只能是抽象方法,总是使用,即使定义时不添加public abstract修饰符,系统也会自动加上。
5. 使用接口
一个类可以实现一个或多个接口,实现接口使用implements关键字。Java中一个类只能继承一个父类,是不够灵活的,通过实现多个接口可以做补充。
6. 继承父类实现接口
如果要继承父类,继承父类必须在实现接口之前(即extends和implements关键字顺序不能反)
**************************************************************************************************************************************
在之前写的代码的基础上,加上一个接口。
由于智能手机还能打游戏,定义一个接口IPlayGame(通常接口名字前加一个‘I’,以区别通常的类)
接口定义处和方法前的abstract关键字都可以省略,系统自动添加
智能手机Smartphone类继承接口IPlayGame,并重写playGame()方法
PSP也有玩游戏功能,继承接口IPlayGame
测试类:
执行结果:
**********************************************************************************************************
五、接口在使用过程中,还经常与匿名内部类配合使用
匿名内部类就是没有名字的内部类,多用于关注实现而不关注实现类的名称。
**************************************************************************************************************************
在刚才的测试类main函数中试写代码
执行结果:
还可以直接new接口实现方法
************************************************************************************************************************************