为什么有接口?
如图所示,动物类为父类,兔子,狗,青蛙为子类。当我们想为狗和青蛙设置动作属性游泳时,发现不能直接在动物父类当中定义,因为兔子不会游泳,那会想到分别在其类当中定义,这样的作法是可以的,但是有个弊端,无法限定子类当中方法书写的格式,方法不统一。所以我们会定义一个接口,定义游泳这个抽象方法,自己定义游泳规则。
接口就相当于定义的规则,可以强制要求狗和青蛙类可以按照接口里面定义的规则来写,代码就统一起来了。所以当我们需要给多给类去定义规则时,就需要用到接口。
就是一种规则,是对行为的抽象。
接口用关键字interface来定义
public interface 接口名{}
接口不能实例化(创建对象)
接口和类之间是实现关系,通过implements关键字表示
public class 类名 implements 接口名 {}
接口和类的实现关系,可以单实现,也可以多实现。
public calss 类名 implements 接口名1,接口名2 {}
实现类还可以在继承一个类的同时实现多个接口。
public class 类名 extends 父类 implements 接口名1,接口名2 {}
现在我们来实际操作一下:
青蛙 属性:名字,年龄 行为:吃虫子,游泳
狗 属性:名字,年龄 行为:吃骨头,狗刨
兔子 属性:名字,游泳 行为:吃胡萝卜
先编写父类,父类中包含它们共有的属性
public 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;
}
//每一个动物吃的东西不一样,所以不写方法体,
//没有方法体的方法是抽象方法,要加上abstract
public abstract void eat();
}
因为兔子不会游泳,所以游泳这个方法不能写在父类中,那么我们就要用接口来定义游泳这个规则。
public interface swim {
//在接口里面定义规则
public abstract void swim();
}
接口定义好,我们继续写实现类,第一个是兔子类,兔子类只需要继承动物类,不需要implements实现游泳类。
public class Rabbit extends Animal {
public Rabbit() {
}
public Rabbit(String name, int age) {
super(name, age);
}
public void eat(){
System.out.println("兔子在吃胡萝卜");
}
}
接下来是狗类,它继续要继承父类,有需要实现游泳类。
public class Dog extends Animal implements swim{
public Dog() {
}
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("狗在吃骨头");
}
@Override
public void swim() {
System.out.println("狗在游泳");
}
}
最后一个是青蛙类,跟狗类的相识
public class Frog extends Animal implements swim{
public Frog() {
}
public Frog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("青蛙在吃虫子");
}
@Override
public void swim() {
System.out.println("青蛙在游泳");
}
}
接下来我们在测试类中进行测试,创建对象
public class Test {
public static void main(String[] args) {
//创建对象
Frog f = new Frog("小青",1);
System.out.println(f.getName()+","+f.getAge());
f.eat();
f.swim();
}
}
输出的结果为:
小青,1
青蛙在吃虫子
青蛙在游泳
只能是常量(不能发生改变的)
默认修饰符:public static final
final:不能改变
static:方便进行调用
public:公共的,在什么地方都可以使用接口里面的常量
没有
只能是抽象方法
默认修饰符:public abstract
JDK7以前:接口中只能定义抽象方法。
继承关系,只能单继承,不能多继承,但是可以多层继承。
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口。在实现类当中实现了多个接口那么要把所有的抽象方法全部重写才可以。
如果多个接口中出现重名的抽象方法,那我们应该怎么办呢?
代码测试一下
我们先定义两个接口
public interface Inter1 {
public abstract void method1();
public abstract void method2();
public abstract void method3();
}
public interface Inter2 {
public abstract void method1();
public abstract void method2();
public abstract void method3();
public abstract void method4();
}
在两个接口里有相同的抽象方法,现在我们定义个实现类
public class InterImpl implements Inter1,Inter2{
@Override
public void method1() {
}
@Override
public void method2() {
}
@Override
public void method3() {
}
@Override
public void method4() {
}
}
结果显而易见,我们只需要定义一次重复的抽象方法
继承关系,可以单继承,也可以多继承。
但是要注意,如果实现类实现了最下面的子接口,那么就需要重写所有的抽象方法
代码演示一下
接口1
public interface Inter1 {
public abstract void method1();
}
接口2
public interface Inter2 {
public abstract void method2();
}
接口3,继承接口1和接口2
public interface Inter3 extends Inter2,Inter1 {
public abstract void method3();
}
实现类实现接口3
public class InterImpl implements Inter3{
@Override
public void method3() {
}
@Override
public void method1() {
}
@Override
public void method2() {
}
}
需要把接口1,2,3的全部抽象方法重写一遍
作用:解决接口升级问题
接口中默认方法的定义格式:
public default 返回值类型 方法名(参数列表){}
范例
public default void show(){}
接口默认方法的注意事项
public interface Inter {
public abstract void method();
public default void show(){
System.out.println("接口中得默认方法---show");
}
}
实现类,只需要重写抽象方法
public class InterImpl implements Inter {
@Override
public void method() {
System.out.println("实现类重写得抽象方法");
}
}
测试类
public class Test {
public static void main(String[] args) {
//创建实现类的对象
InterImpl ii = new InterImpl();
ii.method();
ii.show();
}
}
如果你想重写默认方法,就只需要写它的方法名,按回车,idea会自动书写,但此时重写的方法就不能包含default,不然会报错。
3. public可以省略,default不能省略
4. 如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写
接口中静态方法的定义格式:
public static 返回值类型 方法名(参数列表){}
范例
public static void show(){}
接口中静态方法的注意事项
public interface Inter {
public abstract void method();
public static void show(){
System.out.println("接口中得静态方法");
}
}
实现类
public class InterImpl implements Inter {
@Override
public void method() {
System.out.println("InterImpl重写得抽象方法");
}
//不叫重写,只是刚好与接口中得静态方法重名而已
public static void show(){
System.out.println("InterImpl重写得抽象方法");
}
}
测试类
public class Test {
public static void main(String[] args) {
//调用接口中得静态方法
Inter.show();
//调用实现类里面得静态方法
InterImpl.show();
//重写定义:子类把父类继承下来的虚方法表里面得方法进行覆盖了
//一般静态,私有,最终的都不在虚方法表里
}
}
接口中私有方法的定义格式
格式1
private 返回值类型 方法名(参数列表){}
范例1
private void show()
格式2
private static 返回值类型 方法名(参数列表){}
范例2
private static void method(){}
设计模式是一套被反复使用,多数人知晓的经过分类编目的,代码设计经验的总结,使用设计模式是为了可重用代码,让代码更容易被人理解,保证代码可靠性,程序的重用性。
简单理解:设计模式就是各种套路
适配器设计模式:
解决接口与接口实现类之间的矛盾问题