引入接口思想
继续回到前面的猫狗案例。现在有很多的驯养师可以训练出:猫钻火圈,狗跳高等。而这些额外的动作,并不是所有的猫或者狗一开始就具备的。
所以,这些额外的工作定义到动物类中就不太合适,也不适合直接定义到猫或者狗中,因为只有部分猫或者狗具备这样的功能。
所以,为了体现事物功能的扩展性,java中就提供了接口来定义这些额外的功能,并不给出具体实现,将来哪些猫狗需要被培训,只需要这些猫狗把额外功能实现即可。
接口的特点
1.接口用关键字interface表示,
格式: interface 接口名 {}
2.类实现接口用implements表示,
格式:class 类名 implements 接口名 {}
3.接口不能被实例化
按照多态的方式,由具体的子类实例化,其实这也是多态的一种——接口多态
interface ThainSkill{
//定义一个钻火圈的功能
}
class Demo implements ThainSkill{
}
public class InterfaceDemo1 {
public static void main(String[] args) {
//接口不能直接实例化
// ThainSkill thainskill = new ThainSkill(); 报错
ThainSkill ts = new Demo(); //接口多态
}
}
4. 接口的子类
要么是抽象类,要么是具体类重写接口中的所有抽象方法
来个例子感受一下
abstract class Animal {
private String name;
private int age;
public Animal() {
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public abstract void eat();
}
class Cat extends Animal {
public Cat() {
}
public Cat(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
//定义一个钻火圈的接口
interface ZuanHuoQuan {
void zuanHuo();
}
class TrainCat extends Cat implements ZuanHuoQuan {
public void zuanHuo() {
System.out.println("猫钻火圈");
}
}
public class InterfaceDemo1 {
public static void main(String[] args) {
//定义一个钻火圈的猫
Cat c = new TrainCat();
// c.zuanHuo(); 报错。Cat类中没有zuanHuo()方法
TrainCat tc = (TrainCat) c; //向下转型
tc.zuanHuo();
}
}
接口的成员特点
1.成员变量
只能是常量,并且是静态的
JVM在真正运行之前会自动补齐修饰符:public static final
建议:在学习阶段手动补齐,在开发阶段,省略不写
interface Inter {
public static final int a = 10;
}
public class InterfaceDemo2 {
public static void main(String[] args) {
Inter i = new Demo();
System.out.println(i.a);
//java: 无法为最终变量a分配值
// i.a = 100; 报错
System.out.println(Inter.a);
}
}
2.构造方法
接口中没有构造方法
虽然接口中没有构造方法,但是多态初始化的时候会先初始化父类在初始化子类,这里继承了一个父类——Object,这是java中共同的父类
3.成员方法
接口中的方法只能是抽象方法,没有方法体,连大括号都没有
JVM在真正运行之前会自动补齐修饰符:public abstract
建议:在学习阶段手动补齐,在开发阶段,省略不写
interface Inter {
public static final int a = 10;
//java: 接口抽象方法不能带有主体
// public void fun(){
// System.out.println("玩游戏");
// }
public abstract void fun();
public abstract void fun2();
}
注意:
1.当一个具体的类实现接口的时候,必须实现接口中所有的抽象方法
//当一个具体的类实现接口的时候,必须实现接口中所有的抽象方法
class Demo extends Object implements Inter {
@Override
public void fun() {
System.out.println("Demo类中实现玩游戏方法");
}
@Override
public void fun2() {
System.out.println("Demo类中实现玩游戏方法2");
}
}
2.当一个抽象类实现接口的时候,可以选择不实现接口中的方法,也可以选择性的实现
//当一个抽象类实现接口的时候,可以选择不实现接口中的方法,也可以选择性的实现
abstract class Demo2 implements Inter {
@Override
public void fun() {
System.out.println("抽象类中实现接口抽象方法");
}
}
接口练习
1.猫狗练习,加入跳高的额外功能
分析:
猫: 属性:姓名,年龄 行为:吃饭,睡觉 狗: 属性:姓名,年龄 行为:吃饭,睡觉 由于猫,狗存在共性,所以我们提取出来到一个新的类中 动物:(抽象类) 属性:姓名,年龄 行为:吃饭(),睡觉() 猫:继承自动物 狗:继承自动物 由于跳高是一个额外的功能,不是动物特有的,所以我们利用接口的方式去定义 接口: 跳高 部分的猫:实现接口 部分的狗:实现接口
代码实现:
abstract class Animal4 {
private String name;
private int age;
public Animal4() {
}
public Animal4(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//抽象方法吃饭,睡觉
public abstract void eat();
public abstract void sleep();
}
class Cat4 extends Animal4 {
public Cat4() {
}
public Cat4(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void sleep() {
System.out.println("猫蜷着睡");
}
}
class Dog4 extends Animal4 {
public Dog4() {
}
public Dog4(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("狗吃肉");
}
@Override
public void sleep() {
System.out.println("狗侧着睡");
}
}
interface Jump {
public abstract void jump();
}
//定义部分会跳高的猫
class JumpCat extends Cat4 implements Jump {
public JumpCat() {
}
public JumpCat(String name, int age) {
super(name, age);
}
@Override
public void jump() {
System.out.println("会跳高的猫");
}
}
//定义部分会跳高的狗
class JumpDog extends Dog4 implements Jump {
public JumpDog() {
}
public JumpDog(String name, int age) {
super(name, age);
}
@Override
public void jump() {
System.out.println("会跳高的狗");
}
}
public class InterfaceDemo4 {
public static void main(String[] args) {
//创建一个不会跳高的狗
//抽象多态
Animal4 a1 = new Dog4("小白", 2);
a1.eat();
a1.sleep();
//创建一个会跳高的狗
//多态
Dog4 d1 = new JumpDog("大白", 3);
d1.eat();
d1.sleep();
// d1.jump();
JumpDog jp = (JumpDog) d1;
((JumpDog) d1).jump();
//接口多态
Jump j1 = new JumpDog("大黑", 3);
// j1.eat();
// j1.sleep();
j1.jump();
}
}
2.老师和学生案例,加入抽烟的额外功能
分析:
老师: 属性:姓名,年龄 行为:吃法,睡觉 学生: 属性:姓名,年龄 行为:吃饭,睡觉 由于老师和学生有着共同的属性,抽取出来一个抽象类 人:(抽象类) 属性:姓名,年两 行为:吃饭(),睡觉() 由于不是所有的学生和老师都抽烟,只有部分的老师和学生会 所以,我们将抽烟定义成一个接口 部分的老师:实现抽烟接口 部分的学生:实现抽烟接口
代码实现:
//抽烟的接口
interface Smoking {
public abstract void smoke();
}
//定义抽象父类
abstract class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public abstract void eat();
public void sleep() {
System.out.println("睡觉");
}
;
}
class Teacher extends Person {
public Teacher() {
}
public Teacher(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("老师喝粥");
}
}
class Student extends Person {
public Student() {
}
public Student(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("学生吃烤肉");
}
}
class SmokeTeacher extends Teacher implements Smoking {
public SmokeTeacher() {
}
public SmokeTeacher(String name, int age) {
super(name, age);
}
@Override
public void smoke() {
System.out.println("会抽烟的老师");
}
}
class SmokeStudent extends Student implements Smoking {
public SmokeStudent() {
}
public SmokeStudent(String name, int age) {
super(name, age);
}
@Override
public void smoke() {
System.out.println("会抽烟的学生");
}
}
public class InterfaceDemo5 {
public static void main(String[] args) {
//创建一个不抽烟的学生对象
//抽象多态
Person p1 = new Student("小王", 18);
p1.eat();
p1.sleep();
//创建一个会抽烟的学生对象
//抽象多态
Student p2 = new SmokeStudent("小赵", 20);
p2.eat();
p2.sleep();
((SmokeStudent) p2).smoke();
}
}