接口概述
接口就是一种公共的规范的标准,只要符合规范标准,大家都可以通用 java中的接口更多的体现在对行为的抽象
接口特点
1、接口用关键字interface修饰
2、类实现接口用implements表示。格式如下 public class 类名 implements 接口名 {}
3、接口不能实例化 解决写法: 参照多态的方式,通过实现类对象实例化,这叫接口多态
多态的形式: 具体类多态(几乎不常用)、抽象类多态、接口多态 多态的前提: 有继承或者有实现关系; 有方法重写; 有父类引用指向子类对象或有父接口引用指向实现类对象
接口的实现类: 要么重写接口中的所有抽象方法,要么是抽象类
接口特点的练习
xxxxxxxxxxpackage ch9;
public class a_2_1测试 {
public static void main(String[] args) { a_2_2接口 j = new a_2_3Cat(); //接口的实例化也参照多态的形式 j.jump(); //看上一行。编译看左边,执行看右边 }}xxxxxxxxxxpackage ch9;
//定义了一个接口public interface a_2_2接口 { public abstract void jump();}xxxxxxxxxxpackage ch9;
//继承一下接口。注意类和接口之间是用implements关键字。类实现接口public class a_2_3Cat implements a_2_2接口 {
public void jump() { System.out.println("猫类重写接口类的jump方法"); }}xxxxxxxxxxpackage ch9;
public abstract class a_2_4Dog implements a_2_2接口 {
}
接口的成员特点
成员变量: 1、只能是常量(因为有默认修饰符) 2、默认修饰符:public static final
构造方法: 1、接口没有构造方法,因为接口主要是对行为进行抽象的,是没有具体存在 2、一个类如果没有父类,默认继承自Object类
成员方法: 1、只能是抽象方法,不能是非抽象的 2、默认修饰符:public abstract
接口成员特点的练习
xxxxxxxxxxpackage ch9;
public class a_3_1测试 {
public static void main(String[] args) {
//通过多态创建对象 a_3_2Inter i = new a_3_3InterImpl(); //访问接口里面的num值、num2值 System.out.println(i.num); System.out.println(i.num2);
//i.num2 = 40; //这行会报错,因为在'a_3_2Inter'类里面,num2被final修饰了,此时num2就变成了常量,不允许被重新赋值 //i.num = 41; //这行会报错,虽然在'a_3_2Inter'类里面,num没有被final修饰,但是接口中的变量默认是被final修饰的,即使不写也是
//可以通过接口直接访问接口里面的'常量'。即证明了在'a_3_2Inter'类里面的num和num2是默认被静态修饰的 System.out.println(a_3_2Inter.num); System.out.println(a_3_2Inter.num2); }}x
package ch9;
public interface a_3_2Inter {
//不是成员变量(接口中的变量就是常量) public int num = 10; //num没有被final修饰,但是接口中的变量默认是被final修饰的,即使不写也是。 即是变量 public final int num2 = 20; //num2是常量
//并且上面的num和num2是默认被静态修饰的 public static final int num3 = 30; //即public static final是可以不写的,即直接写int num3 = 30也不会报错 int num4 = 31;
//----------------------------------------------------------------------------------------------
//构造方法 //public a_3_2Inter() {} //这行会报错,说明接口里面是不允许写构造方法的,即接口没有构造方法
//-----------------------------------------------------------------------------------------------
//成员方法 //public void show() {} //这行会报错,说明接口里面是不允许有非抽象方法的,即接口没有非抽象方法 public abstract void method(); //不报错,说明接口里面允许有抽象方法。但是再在'a_3_3InterImpl'类里重写method(),不然那里会报错 //提示:上面那行可以省略public abstract不写,系统会默认你写了
}xxxxxxxxxxpackage ch9;
//接口的实现类//public class a_3_3InterImpl implements a_3_2Inter { }
//上面那行的作用跟下面那行一样//public class a_3_3InterImpl extends Object implements a_3_2Inter {}
public class a_3_3InterImpl extends Object implements a_3_2Inter { //这里的Object是固定写法 public a_3_3InterImpl() { super(); //注意这里的super使用的是Object里面的构造方法。并不是接口里面的构造方法,因为接口不存在构造方法 }
//------------------------------------------------------------------------------------------
//成员方法 //不允许有非抽象方法的,即接口没有非抽象方法 //对于抽象方法,一定要在这里重写一下,不然第9行会报错。重写如下 public void method() { System.out.println("我是重写method方法"); }}
猫和狗_接口版
需求: 对猫和狗进行训练,它们就可以跳高了,这里加入了跳高功能。请采用抽象类和接口来实现猫和狗案例
思路如下:
1、定义接口 成员方法: 跳高(); 注意跳高这个方法是抽象的
2、定义抽象动物类 成员变量: 姓名,年龄; 构造方法: 无参,带参 成员方法: get和set方法,吃饭(); 注意跳高这个方法是抽象的
3、定义具体猫类,继承动物类,实现跳高接口 构造方法: 无参,带参 成员方法: 重写吃饭方法,重写跳高方法
4、定义狗类,继承动物类,实现跳高接口 构造方法: 无参,带参 成员方法: 重写吃饭方法,重写跳高方法
5、定义测试类,并测试
注意这里只用代码演示猫类的,狗类的同理就不重复写了
猫和狗_接口版的练习
xxxxxxxxxxpackage ch9;
public interface a_4_1接口 {
public abstract void jump(); //提示: 可以省略public abstract不写 。 这里的jump()就是所谓的跳高方法 }x
package ch9;
//加abstract表示抽象的,定义成员变量public abstract class a_4_2Animal {
private String name; private int age;
//无参构造方法 public a_4_2Animal() { }
//带参构造方法 public a_4_2Animal(String name, int age) { this.name = name; this.age = age; }
//get和set方法 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(); //加abstract表示抽象的方法
}xxxxxxxxxxpackage ch9;
//继承动物类,实现跳高接口public class a_4_3Cat extends a_4_2Animal implements a_4_1接口 { //无参构造方法 public a_4_3Cat() { }
//带参构造方法 public a_4_3Cat(String name, int age) { super(name, age); }
//必须要重写'a_4_2Animal'里面的eat方法 和 'a_4_1接口'里面的jump方法 public void eat() { System.out.println("猫类重写父类的eat方法"); }
public void jump() { System.out.println("猫类重写接口类的jump方法"); }}xxxxxxxxxxpackage ch9;
public class a_4_4测试 { public static void main(String[] args) {
//使用无参构造方法来创建对象,并调用方法。用接口来演示 a_4_1接口 j = new a_4_3Cat(); j.jump(); System.out.println("-----------------"); //接口不能调用get和set方法,因为接口不存在get和set方法 //【接口只能调用接口里面的方法】
//使用无参构造方法来创建对象,并调用方法。 a_4_2Animal a = new a_4_3Cat(); a.setName("猫名-无参"); a.setAge(2); System.out.println(a.getName() + "," + a.getAge()); a.eat(); //a.jump(); //这行这样写会报错,要把jump强转为'a_4_3Cat'类,如下 ((a_4_3Cat) a).jump(); System.out.println("-----------------"); //【抽象类只能调用抽象类里面的方法】
//使用带参构造来创建对象,并调用方法 a = new a_4_3Cat("猫名-带参",3); System.out.println(a.getName() + "," + a.getAge()); a.eat(); ((a_4_3Cat) a).jump(); //这个jump要把a强转为'a_4_3Cat'类才能使用 System.out.println("-----------------");
//---------------------------------------------------------------------------------------------
//以前的用法-无参(推荐这种用法哦,因为'a_4_3Cat'类里面有最多的方法): a_4_3Cat c = new a_4_3Cat(); c.setName("猫名-常用写法-无参"); c.setAge(5); System.out.println(c.getName() + "," + c.getAge()); c.eat(); c.jump(); //这里不用强转就可以调用 System.out.println("-----------------");
//以前的用法-带参(推荐这种用法哦,因为'a_4_3Cat'类里面有最多的方法): c = new a_4_3Cat("猫名-常用写法-带参",4); System.out.println(c.getName() + "," + c.getAge()); c.eat(); c.jump(); //这里不用强转就可以调用 System.out.println("-----------------");
}}
类和接口的关系
类和类的关系: 继承关系。但是可以多层继承
类和接口的关系: 实现关系。可以单实现也可以多实现,还可以在在继承一个类的同时实现多个接口(后半句话待会代码演示)
接口和接口的关系: 继承关系。可以单继承,也可以多继承
类和接口关系的练习
xxxxxxxxxxpackage ch9;
//接口实现接口public interface a_5_1接口1 extends a_5_2接口2,a_5_3接口3 { //接口和接口是继承关系,并且可以多继承
}xxxxxxxxxxpackage ch9;
public interface a_5_2接口2 { }xxxxxxxxxxpackage ch9;
public interface a_5_3接口3 {
}xxxxxxxxxxpackage ch9;
//这里探究类和接口的关系//首先先在类里面写implements关键字,作用是实现接口(实现'a_5_1接口1'和'a_5_2接口2'和'a_5_3接口3'接口,注意用逗号隔开)//public class a_5_4InterImpl implements a_5_1接口1,a_5_2接口2,a_5_3接口3 { //一个类可以同时实现多个接口,类还可以再继承类,如下public class a_5_4InterImpl extends Object implements a_5_1接口1,a_5_2接口2,a_5_3接口3 {//类继承类,同时类实现多接口
}
抽象类和接口的区别
成员区别: 抽象类: 可以有常量、变量、构造方法、抽象方法、非抽象方法 接口: 只能有常量、抽象方法
关系区别: 类与类: 继承,且只能单继承 类与接口: 实现,可以单实现也可以多实现 接口与接口: 继承: 可以单继承也可以多继承
设计理念区别: 抽象类: 对类抽象,包括属性、行为 接口: 对行为抽象,主要是行为
xxxxxxxxxxpackage ch9;
public class a_6_0抽象类和接口的区别 {
/* 举个例子: 门和警报
门和是主体,功能有关、开、发出警报
门: 都有open()和close()两个动作,我们可以分别使用抽象类和接口来定义这个抽象概念
//抽象类的写法 //接口类的写法 public abstract class Door { public interface Door { public abstract void open(); void open(); public abstract void close(); void close(); } } */
//如何实现,如下(关和开是门的基本功能,发出警报是额外功能,把基本功能放到抽象类里面,让门继承抽象类和实现报警接口): public interface Alram { //实现报警接口 void alarm(); } public abstract class Door { //抽象类 public abstract void open(); //抽象方法 public abstract void close(); //抽象方法 } public class AlarmDoor extends Door implements Alarm {//报警门继承Door这个抽象类,并且报警门实现报警接口 public void open() { //...... } public void close() { //...... } public void alarm() { //...... } }
//总结: 抽象类是对事物的抽象,而接口是对行为的抽象 }
运动员和教练案例
需求: 我们现在有乒乓球运动员和篮球运动员、乒乓球教练和篮球教练。为了出国交流,跟乒乓球相关的人员都需要学习英语。 请分析案例中有哪些具体类、抽象类、接口。并用代码实现
分析(具体的,所以下面都是具体的类): 1、乒乓球运动员 2、篮球运动员 3、乒乓球教练 4、篮球教练
将1和2提取出一个抽象的运动员类,里面有一个学习()抽象方法 将3和4提取出一个抽象的教练类,里面有一个教()抽象方法 将运动员类和教练类提取出一个抽象的人类,里面有姓名、年龄的成员变量和吃饭()的成员方法 定义一个接口,叫学习英语。让1和3实现这个接口
注意: 实现时我们需要从抽象到具体,使用时我们需要使用具体的类的对象,因为里面的内容最多
分析完毕我们来讲一下思路: 1、定义说英语接口。里面包含成员方法即说英语() 2、定义抽象人类。里面包含成员变量即姓名、年龄。包含构造方法即无参、包括带参。包括成员方法即get和set方法、吃饭() 3、定义抽象教练类,继承人类。里面包含构造方法即无参、带参。包括成员方法即教() 4、定义抽象运动员类,继承人类。里面包含构造方法即无参、带参。包括成员方法即学习() 5、定义具体篮球教练类,继承教练类。里面包含构造方法即无参、带参。包括成员方法即重写吃饭方法和重写教方法 6、定义具体乒乓球教练类,继承教练类,实现说英语接口。里面包含构造方法即无参、带参。包括成员方法即重写吃饭方法和重写教方法和重写说英语 7、定义具体篮球运动员类,继承运动员类。里面包含构造方法即无参、带参。包括成员方法即重写吃饭方法和重写学习方法 8、定义具体乒乓球运动员类,继承运动员类,实现说英语接口。里面包含构造方法即无参、带参。包括成员方法即重写吃饭方法和重写学习方法和重写说英语方法 9、定义测试类并测试
xxxxxxxxxxpackage ch9;
//抽象教练类,并继承人类public abstract class a_7_1Coach extends a_7_2Person {
//无参构造方法 public a_7_1Coach() { }
//带参构造方法 public a_7_1Coach(String name, int age) { super(name, age); }
//抽象的teach方法 public abstract void teach();
}xxxxxxxxxxpackage ch9;
//抽象人类public abstract class a_7_2Person {
//成员变量 private String name; private int age;
//无参构造方法 public a_7_2Person() {}
//带参构造方法 public a_7_2Person(String name, int age) { this.name = name; this.age = age; }
//get和set方法 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; }
//抽象的eat方法 public abstract void eat(); }xxxxxxxxxxpackage ch9;
//抽象运动员类,并继承人类public abstract class a_7_3Player extends a_7_2Person {
//无参构造方法 public a_7_3Player() { }
//带参构造方法 public a_7_3Player(String name, int age) { super(name, age); }
//抽象的study方法 public abstract void study(); }xxxxxxxxxxpackage ch9;
//说英语接口public interface a_7_4接口 { public abstract void speak();}package ch9;
//具体的篮球教练类,并继承教练类public class a_7_5BasketballCoach extends a_7_1Coach {
//重写a_7_1Coach和a_7_2Person的方法,即重新teach()和eat()。不然上面一行会报错 public void teach() { System.out.println("具体的篮球教练类-重写teach()"); } public void eat() { System.out.println("具体的篮球教练类-重写eat()"); }
//无参构造方法 public a_7_5BasketballCoach() { }
//带参构造方法 public a_7_5BasketballCoach(String name, int age) { super(name, age); }}xxxxxxxxxxpackage ch9;
//具体的乒乓球教练类,并继承教练类。跟乒乓球相关的还要实现一个接口,用implements关键字,还要重写接口里的speak方法public class a_7_6PingPangCoach extends a_7_1Coach implements a_7_4接口 {
//重写a_7_1Coach和a_7_2Person的方法,即重写teach()和eat()和接口里的speak方法。不然上面一行会报错 public void teach() { System.out.println("具体的乒乓球教练类-重写teach()"); } public void eat() { System.out.println("具体的乒乓球教练类-重写eat()"); } public void speak() { System.out.println("具体的乒乓球教练类-重写speak()"); }
//无参构造方法 public a_7_6PingPangCoach() { }
//带参构造方法 public a_7_6PingPangCoach(String name, int age) { super(name, age); }}xxxxxxxxxxpackage ch9;
//具体的篮球运动员类,并继承运动员类public class a_7_7BasketballPlayer extends a_7_3Player {
//重写a_7_3Player的方法,即重写study()。不然上面一行会报错 //因为'a_7_3Player'继承了'a_7_2Person'类,所以这里还需要重写'a_7_2Person'类里面的eat() public void study() { System.out.println("具体的篮球运动员类-重写study()"); } public void eat() { System.out.println("具体的篮球运动员类-重写eat()"); }
//无参构造方法 public a_7_7BasketballPlayer() { }
//带参构造方法 public a_7_7BasketballPlayer(String name, int age) { super(name, age); }}xxxxxxxxxxpackage ch9;
//具体的乒乓球运动员类,并继承运动员类。实现说英语的接口,即用implements关键字public class a_7_8PingPangPlayer extends a_7_3Player implements a_7_4接口{
public void study() { System.out.println("具体的乒乓球运动员类-重写study()"); } public void eat() { System.out.println("具体的乒乓球运动员类-重写eat()"); } public void speak() { System.out.println("具体的乒乓球运动员类-重写speak()"); }
//无参构造方法 public a_7_8PingPangPlayer() { }
//带参构造方法 public a_7_8PingPangPlayer(String name, int age) { super(name, age); }
}xxxxxxxxxxpackage ch9;
//测试类public class a_7_9测试 {
public static void main(String[] args) {
//无参构造方法创建对象-乒乓球运动员。这里用无参,也可以用带参 a_7_8PingPangPlayer ppp = new a_7_8PingPangPlayer(); ppp.setName("张继科"); ppp.setAge(30); System.out.println(ppp.getName() + "," + ppp.getAge()); ppp.study(); ppp.speak();
System.out.println("---------------"); //无参构造方法创建对象-乒乓球教练。这里用无参,也可以用带参 a_7_6PingPangCoach coa = new a_7_6PingPangCoach(); coa.setName("刘国梁"); coa.setAge(40); System.out.println(coa.getName() + "," + coa.getAge()); coa.teach(); coa.speak();
//---------------------------------------------------------------------------------------------------------
System.out.println("----------------------------"); //无参构造方法创建对象-篮球运动员。这里用无参,也可以用带参 a_7_7BasketballPlayer bp = new a_7_7BasketballPlayer(); bp.setName("科比"); bp.setAge(31); System.out.println(bp.getName() + "," + bp.getAge()); bp.eat(); bp.study();
System.out.println("---------------"); //无参构造方法创建对象-篮球教练。这里用无参,也可以用带参 a_7_5BasketballCoach bco = new a_7_5BasketballCoach(); bco.setName("菲尔·杰克逊"); bco.setAge(41); System.out.println(bco.getName() + "," + bco.getAge()); bco.teach(); bco.eat(); }}