多态、引用类型转换、抽象类、接口

一、多态

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接口实现方法
多态、引用类型转换、抽象类、接口

************************************************************************************************************************************