接口
1、接口定义:
与定义类的class不同,接口定义时需要使用interface关键字。
定义接口所在的仍为.java文件,虽然声明时使用的为interface关键字的编译后仍然会产生.class文件。这点可以让我们将接口看做是一种只包含了功能声明的特殊类。
定义格式:
public interface 接口名 {
抽象方法1;
抽象方法2;
抽象方法3;
}
使用interface代替了原来的class,其他步骤与定义类相同:
接口中的方法均为公共访问的抽象方法
接口中无法定义普通的成员变量
/*
* 定义接口
* 使用关键字interface 接口名字
* 接口定义:
* 成员方法,全抽象
* 不能定义带有方法体的方法
*
* 定义抽象方法: 固定格式
*
* public abstract 返回值类型 方法名字(参数列表);
* 修饰符 public 写,或者不写,都是public
*
* 接口中成员变量的定义
* 成员变量的定义,具体要求
*
* 要求 : 必须定义为常量
* 固定格式:
* public static final 数据类型 变量名 = 值
*/
类与接口的关系为实现关系,即类实现接口。实现的动作类似继承,只是关键字不同,实现使用implements。
接口中成员的特点
- 1. 成员变量的特点, 没有变量,都是常量
- 固定定义格式: public static final 数据类型 变量名 = 值
public 权限
static 可以被类名直接.调用
final 最终,固定住变量的值
//
- 注意: public static final 修饰符,在接口的定义中,可以省略不写
- 但是,!!!不写不等于没有,即便是int x = 3 他仍然不可修改
- 三个修饰符,还可以选择性书写
-
- 接口中的成员方法特点:
-
public abstract 返回值类型 方法名(参数列表)
-
修饰符 public abstract 可以不写,选择性书写
-
但是,写不写,都有
-
- 实现类,实现接口,重写接口全部抽象方法,创建实现类对象
-
实现类,重写了一部分抽象方法,实现类,还是一个抽象类
*/
class + MyInterfaceImp1 + implements + MyInterface
class 类 实现 接口
定义类, 实现接口,重写接口中的抽象方法
创建实现类的对象
类实现接口, 可以理解为继承
关键字 implements
- class 类 implements 接口{
-
重写接口中的抽象方法
- }
-
类 实现 接口
- class MyInterfaceImpl implements MyInterface
接口的多实现:
多实现没有安全隐患,原因在于接口中的方法全是抽象,没有主体
- 类C,同时去实现2个接口,接口A,B
- 作为实现类,C,***全部重写***两个接口的所有抽象方法,才能建立C类的对象
*** C类,在继承一个类的同时,可以实现多个接口***
必须同时对继承的抽象类、接口中的抽象方法都要进行重写,才能够运行
接口之间的多继承
day11: demo04
一个接口可以继承多个接口
/*
- 实现接口C,重写C接口的全部抽象方法
- 而且接口C,继承A,B
- D实现类,重写A,B,C三接口全部抽象方法
- 问: Java中有多继承吗
- 类没有多继承
- 接口之间多继承
*/
接口和抽象类的区别
相同点:
都位于继承的顶端,用于被其他类实现或继承;
都不能直接实例化对象;
都包含抽象方法,其子类都必须覆写这些抽象方法;
区别:
抽象类为部分方法提供实现,避免子类重复实现这些方法,提高代码重用性;接口只能包含抽象方法;
一个类只能继承一个直接父类(可能是抽象类),却可以实现多个接口;(接口弥补了Java的单继承)
抽象类是这个事物中应该具备的你内容, 继承体系是一种 is…a关系
接口是这个事物中的额外内容,继承体系是一种 like…a关系
二者的选用:
优先选用接口,尽量少用抽象类;
需要定义子类的行为,又要为子类提供共性功能时才选用抽象类;
多态性:day11demo5
下面的文字抄的
多态性是对象多种表现形式的体现。
现实中,比如我们按下 F1 键这个动作:
如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;
如果当前在 Word 下弹出的就是 Word 帮助;
在 Windows 下弹出的就是 Windows 帮助和支持。
同一个事件发生在不同的对象上会产生不同的结果。
多态的优点
- 消除类型之间的耦合关系
- 可替换性
- 可扩充性
- 接口性
- 灵活性
- 简化性
多态存在的三个必要条件
继承
重写
父类引用指向子类对象
比如:
Parent p = new Child();
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。
以下是一个多态实例的演示,详细说明请看注释:
Test.java 文件代码:
public class Test {
public static void main(String[] args) {
show(new Cat()); // 以 Cat 对象调用 show 方法
show(new Dog()); // 以 Dog 对象调用 show 方法
Animal a = new Cat(); // 向上转型
a.eat(); // 调用的是 Cat 的 eat
Cat c = (Cat)a; // 向下转型
c.work(); // 调用的是 Cat 的 work
}
从这之上是抄的
Java实现多态有三个必要条件:继承、重写、向上转型。
// 多态调用方法,方法必须运行子类的重写!!
//Java中,对象的多态性,调用程序中的方法
// 公式: 父类类型或者是接口类型 变量 = new 子类的对象();
Fu f = new Zi();
package cn.itcast.demo05;
public class Test {
public static void main(String[] args) {
// 多态调用方法,方法必须运行子类的重写!!
//Java中,对象的多态性,调用程序中的方法
// 公式: 父类类型或者是接口类型 变量 = new 子类的对象();
Fu f = new Zi();
f.show();
//抽象类Animal,子类是Cat
Animal a = new Cat();
a.eat();
//接口Smoking,实现类Student
Smoking sk = new Student();
sk.smoking();
}
}
- 多态中,成员特点
- Fu f = new Zi();
- f.a成员变量对应的是父类中的成员变量
- 成员变量:
-
***编译的时候, 参考父类中有没有这个变量,如果有,编译成功,没有编译失败***
-
***运行的时候, 运行的是父类中的变量值***
- 编译运行全看父类
- 成员方法:
- f.show()需要在父类中有这个show方法,父类没有编译失败,如果子类有则运行子类的方法,如果子类没有这个show方法,则运行父类的方法,如果父类没有show方法,那么就报错了
-
***编译的时候, 参考父类中有没有这个方法,如果有,编译成功,没有编译失败***
-
***运行的时候, 运行的是子类的重写方法***
- 编译看父类,运行看子类
- 注意:要看清是多态还是子类
- 多态: Fu a = new Zi();
- 子类: Zi a = new Zi();这个是子类,完全可以在父类中没有show方法的条件下运行show(子类有)
关键字:Instanceof,
- 运算符比较运算符, 结果真假值
- 关键字, instanceof, 比较引用数据类型
- Person p = new Student();
- p = new Teacher() //Person p = new Teacher()这种方法则重复定义错误
- 上边先将p定义成学生,再将其定义为老师,最后p是老师类,经过instanceof判断是否为学生类时,则返回false
- 关键字 instanceof 比较, 一个引用类型的变量,是不是这个类型的对象
- p变量,是Student类型对象,还是Teacher类型对象
- 引用变量 instanceof 类名
- p instanceof Student 比较,p是不是Student类型的对象,如果是,intanceof返回true
多态中的转型
Fu f = new Zi();
向上转型:当有子类对象赋值给一个父类引用时,便是向上转型,多态本身就是向上转型的过程。
父类类型 变量名 = new 子类类型();
如:Person p = new Student();
向下转型:一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用转为子类引用,这个过程是向下转型。如果是直接创建父类对象,是无法向下转型的!
子类类型 变量名 = (子类类型) 父类类型的变量;
如:Student stu = (Student) p; //变量p 实际上指向Student对象
package cn.itcast.demo08;
/*
- 测试类
-
- 实现动物和Cat,Dog多态调用
-
- 做类型的强制转换,调用子类的特有功能
*/
- 做类型的强制转换,调用子类的特有功能
public class Test {
public static void main(String[] args) {
//两个子类,使用两次多态调用
Animal a1 = new Cat();
Animal a2 = new Dog();
//a1,a2调用子类父类共有方法,运行走子类的重写
a1.eat();
a2.eat();
//类型向下转型,强制转换,调用子类的特有
//防止发生异常: a1属于Cat对象,转成Cat类, a2属于Dog对象,转成Dog
//instanceof判断
if(a1 instanceof Cat){
Cat c = (Cat)a1;
c.catchMouse();
}
if(a2 instanceof Dog){
Dog d = (Dog)a2;
d.lookHome();
}
}
}