接口概述
接口就是一种公共的规范的标准,只要符合规范标准,大家都可以通用 java中的接口更多的体现在对行为的抽象
接口特点
1、接口用关键字interface修饰
2、类实现接口用implements表示。格式如下 public class 类名 implements 接口名 {}
3、接口不能实例化 解决写法: 参照多态的方式,通过实现类对象实例化,这叫接口多态
多态的形式: 具体类多态(几乎不常用)、抽象类多态、接口多态 多态的前提: 有继承或者有实现关系; 有方法重写; 有父类引用指向子类对象或有父接口引用指向实现类对象
接口的实现类: 要么重写接口中的所有抽象方法,要么是抽象类
接口特点的练习
xxxxxxxxxx
package ch9;
public class a_2_1测试 {
public static void main(String[] args) {
a_2_2接口 j = new a_2_3Cat(); //接口的实例化也参照多态的形式
j.jump(); //看上一行。编译看左边,执行看右边
}
}
xxxxxxxxxx
package ch9;
//定义了一个接口
public interface a_2_2接口 {
public abstract void jump();
}
xxxxxxxxxx
package ch9;
//继承一下接口。注意类和接口之间是用implements关键字。类实现接口
public class a_2_3Cat implements a_2_2接口 {
public void jump() {
System.out.println("猫类重写接口类的jump方法");
}
}
xxxxxxxxxx
package ch9;
public abstract class a_2_4Dog implements a_2_2接口 {
}
接口的成员特点
成员变量: 1、只能是常量(因为有默认修饰符) 2、默认修饰符:public static final
构造方法: 1、接口没有构造方法,因为接口主要是对行为进行抽象的,是没有具体存在 2、一个类如果没有父类,默认继承自Object类
成员方法: 1、只能是抽象方法,不能是非抽象的 2、默认修饰符:public abstract
接口成员特点的练习
xxxxxxxxxx
package 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不写,系统会默认你写了
}
xxxxxxxxxx
package 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、定义测试类,并测试
注意这里只用代码演示猫类的,狗类的同理就不重复写了
猫和狗_接口版的练习
xxxxxxxxxx
package 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表示抽象的方法
}
xxxxxxxxxx
package 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方法");
}
}
xxxxxxxxxx
package 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("-----------------");
}
}
类和接口的关系
类和类的关系: 继承关系。但是可以多层继承
类和接口的关系: 实现关系。可以单实现也可以多实现,还可以在在继承一个类的同时实现多个接口(后半句话待会代码演示)
接口和接口的关系: 继承关系。可以单继承,也可以多继承
类和接口关系的练习
xxxxxxxxxx
package ch9;
//接口实现接口
public interface a_5_1接口1 extends a_5_2接口2,a_5_3接口3 { //接口和接口是继承关系,并且可以多继承
}
xxxxxxxxxx
package ch9;
public interface a_5_2接口2 {
}
xxxxxxxxxx
package ch9;
public interface a_5_3接口3 {
}
xxxxxxxxxx
package 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 {//类继承类,同时类实现多接口
}
抽象类和接口的区别
成员区别: 抽象类: 可以有常量、变量、构造方法、抽象方法、非抽象方法 接口: 只能有常量、抽象方法
关系区别: 类与类: 继承,且只能单继承 类与接口: 实现,可以单实现也可以多实现 接口与接口: 继承: 可以单继承也可以多继承
设计理念区别: 抽象类: 对类抽象,包括属性、行为 接口: 对行为抽象,主要是行为
xxxxxxxxxx
package 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、定义测试类并测试
xxxxxxxxxx
package 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();
}
xxxxxxxxxx
package 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();
}
xxxxxxxxxx
package 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();
}
xxxxxxxxxx
package 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);
}
}
xxxxxxxxxx
package 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);
}
}
xxxxxxxxxx
package 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);
}
}
xxxxxxxxxx
package 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);
}
}
xxxxxxxxxx
package 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();
}
}