Java_接口和多态
一.接口
1.接口概述和特点
- 接口也是一种规范
接口的格式如下:
- 接口用关键字interface来定义
public interface 接口名 {
// 常量
// 抽象方法}
- JDK8之前接口中只能是抽象方法和常量,没有其他成分了。
接口不能实例化。
接口中的成员都是public修饰的,写不写都是,因为规范的目的是为了公开化。
2.接口的基本使用:被实现
接口的用法:
-
接口是用来被类实现(implements)的,实现接口的类称为实现类。实现类可以理解成所谓的子类。
-
修饰符 class 实现类 implements 接口1, 接口2, 接口3 , … {}
实现的关键字:implements
接口可以被类单实现,也可以被类多实现。
接口实现的注意事项:
一个类实现接口,必须重写完全部接口的全部抽象方法,否则这个类需要定义成抽象类。
public interface SportMan {
void run();
void competition();
}
public interface Law {
void rule();
}
/**
实现类。
*/
public class PingPongMan implements SportMan,Law{
private String name;
public PingPongMan(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println(name + "必须跑步训练");
}
@Override
public void competition() {
System.out.println(name + "必须参加比赛");
}
@Override
public void rule() {
System.out.println(name + "也要遵守规则~~");
}
}
public class Test {
public static void main(String[] args) {
//目标:理解接口的基本使用,被类实现
PingPongMan p = new PingPongMan("马龙");
p.competition();
p.run();
p.rule();
}
}
小结:
-
类和类的关系:单继承。
-
类和接口的关系:多实现。
-
接口和接口的关系:多继承,一个接口可以同时继承多个接口。
接口多继承的作用:
规范合并,整合多个接口为同一个接口,便于子类的实现
3.jdk8开始接口新增的方法
- 允许接口中直接定义带有方法体的方法
第一种:默认方法
类似之前写的普通实例方法:必须用default修饰
默认会public修饰。需要用接口的实现类的对象来调用
default void run(){System.out.println(“”);}
第二种:静态方法
默认会public修饰,必须static修饰。
注意:接口的静态方法必须用本身的接口名来调用。
static void inAddr(){System.out.println(“”); }
第三种:私有方法
就是私有的实例方法:,必须使用private修饰,从JDK 1.9才开始有的。
只能在本类中被其他的默认方法或者私有方法访问。
private void go(){System.out.println(“”);}
public interface SportMan {
/**
1.JDK 8开始,默认方法(实例方法)
--必须default修饰,默认用public修饰
--默认方法,接口不能创建对象,这个方法只能过继给实现类,由实现类的对象调用
*/
default void run(){
go();
System.out.println("跑起来~~~");
}
/**
2.静态方法:
必须使用static修饰,默认使用public修饰
--接口的静态方法,必须由接口名自己调用。
*/
static void inAddr(){
System.out.println("跑的贼快");
}
/**
3.私有方法
--jdk9开始支持的
--必须由接口内部才能被访问
*/
private void go(){
System.out.println("快润呀~~~");
}
}
class PingPongMan implements SportMan{}
class Test{
public static void main(String[] args) {
PingPongMan p = new PingPongMan();
p.run();
SportMan.inAddr();
}
}
4.使用接口的注意事项
接口的注意事项
1、接口不能创建对象
2、一个类实现多个接口,多个接口的规范不能冲突
2、一个类实现多个接口,多个接口中有同样的静态方法不冲突。
3、一个类继承了父类,同时又实现了接口,父类中和接口中有同名方法,默认用父类的。
4、一个类实现了多个接口,多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可。
5、一个接口继承多个接口,是没有问题的,如果多个接口中存在规范冲突则不能多继承。
二.多态
1.多态概述
**多态:**指对象可以有多种形态。
**多态的常见形式:**父类类型 对象名称= new 子类构造器;
多态中成员访问特点
方法调用:编译看左边,运行看右边。
变量调用:编译看左边,运行也看左边。(注意)
多态的前提
有继承/实现关系;有父类引用指向子类对象;有方法重写(多态侧重行为多态)。
2.多态的优势
-
在多态形式下,右边对象可以实现解耦合,便于扩展和维护。
-
定义方法的时候,使用父类型作为参数,该方法就可以接收这父类的一切子类对象,体现出多态的扩展性与便利。
多态下会产生的一个问题:
- 多态下不能使用子类的独有功能
3.多态下: 类型转换问题
**自动类型转换(从子到父):**Animal c = new Cat();
强制类型转换(从父到子):
从父到子( 必须进行强制类型转换,否则报错): 子类 对象变量 = (子类)父类类型的变量
-
作用:可以解决多态下的劣势,可以实现调用子类独有的功能。
-
注意: 有继承/实现关系的类就可以在编译阶段进行强制类型转换;但是,如果转型后的类型和对象真实对象的类型不是同一种类型,那么在运行代码时,就会出现ClassCastException
Animal c = new Cat();
Dog d = (Dog)c; // 出现异常 ClassCastException
Java建议强转转换前使用instanceof判断当前对象的真实类型,再进行强制转换
变量名 instanceof 真实类型
判断关键字左边的变量指向的对象的真实类型,是否是右边的类型或者是其子类类型,是则返回true,反之。
4.案例
需求:
模拟开发一款动物表演类的游戏
分析:
①定义一个USB的接口(申明USB设备的规范必须是:可以接入和拔出)。
②提供2个USB实现类代表鼠标和键盘,让其实现USB接口,并分别定义独有功能。
③创建电脑对象,创建2个USB实现类对象,分别安装到电脑中并触发功能的执行。
/**
usb接口 = 规范
*/
public interface USB {
//插入 拔出
void connect();
void unconnect();
}
/**
实现类
*/
public class KeyBoard implements USB{
private String name;
public KeyBoard(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void connect() {
System.out.println(name + "成功连接了电脑~~~");
}
@Override
public void unconnect() {
System.out.println(name + "成功从电脑中拔出~~~");
}
/**
独有功能
*/
public void keDown(){
System.out.println(name + "键盘还在输出~~~");
}
}
/**
实现类
*/
public class Mouse implements USB{
private String name;
public Mouse(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void connect() {
System.out.println(name + "成功连接了电脑~~~");
}
@Override
public void unconnect() {
System.out.println(name + "成功从电脑中拔出~~~");
}
/**
独有功能
*/
public void dbClick(){
System.out.println(name + "鼠标正在疯狂输出~~~");
}
}
public class Computer {
private String name;
public Computer(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void Start(){
System.out.println(name + "开始工作~~~");
}
/**
提供安装usb设备的入口
*/
public void installUSB (USB usb){
// 多态 usb == 可能是鼠标 也可能是键盘
usb.connect();
//独有功能:先判断再强转
if (usb instanceof KeyBoard){
KeyBoard k = (KeyBoard) usb;
k.keDown();
}else if (usb instanceof Mouse){
Mouse m = (Mouse) usb;
m.dbClick();
}
usb.unconnect();
}
}
/**
目标:USB设备模拟
1.定义usb接口,插入 拔出
2.定义2个usb的实现类,鼠标,键盘
3.创建一个电脑对象,创建usb设备对象,安装启动
*/
public class Test {
public static void main(String[] args) {
//1.创建电脑对象
Computer c = new Computer("败家之眼~~~");
c.Start();
//2.创建鼠标对象,键盘对象
USB u = new Mouse("罗技G703");
c.installUSB(u);
USB u2 = new KeyBoard("阿米洛~~~");
c.installUSB(u2);
}
}