一、抽象方法与抽象类
1.定义
抽象方法:将共性的方法抽取到父类以后,由于每个子类执行的内容是不一样的,所以,在父类中不能确定具体的方法体,该方法就可以定义为抽象方法
只有声明没有方法体的方法就叫抽象方法,包含着一个或者多个抽象方法的类叫做抽象类
抽象类:如果一个类中存在抽象方法,那么该类就必须声明为抽象类
抽象类也可以有构造方法,普通成员变量和方法,也可以派生抽象类的子类
2.定义格式
抽象方法:public abstract 返回值类型 方法名(参数列表);(没有方法体)
抽象类:public abstract class 类名{}
3.注意事项
a.抽象类不能实例化
b.抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
c.可以有构造方法 作用:创建子类对象时,给属性进行赋值的
d.抽象类的子类要么重写抽象类中的所有抽象方法,要么是抽象类
如果抽象类的子类实现了抽象方法,可以创建该子类的实例对象;否则该子类也是抽象类,不能创建实例;
4.例子
package Abstract;
public abstract class Animal {
private String name;
private int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public Animal(){
}
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 void drink(){
System.out.println(name+"在喝水");
}
public abstract void eat();
}
package Abstract;
public class Frog extends Animal{
public Frog(String name, int age) {
super(name, age);
}
public Frog() {
}
@Override
public void eat() {
System.out.println("青蛙吃虫");
}
}
package Abstract;
public class Test {
public static void main(String[] args) {
Frog f = new Frog("A",1);
System.out.println(f.getName()+","+f.getAge());
f.drink();
f.eat();
}
}
二、接口
接口是一种规则,是对行为的抽象
1.定义接口
a.接口通过关键字interface来定义 public interface 接口名{}
b.接口不能实例化
c.接口和类是实现关系,通过implements关键字表示 public class 类名 implements 接口名{} ; 一个类可以实现多个接口:public class 类名 implements 接口名1,接口名2{}
d. 接口的子类(实现类) 要么重写接口中所有的抽象方法,要么是抽象类
e.实现类还可以在继承一个类的同时实现多个接口
public class 类名 extends 父类 implements 接口名1,接口名2{}
2.接口中的成员特点
成员变量:只能是常量 ;默认修饰符 public static final
构造方法:没有
成员方法:只能是抽象方法 默认修饰符:public abstract
接口中只进行方法的声明,不提供方法的实现;所以,方法定义没有方法体,而且以;结尾
多个接口里面的方法重名,只需要重写一个
3.接口的实现与使用
在类体中可以使用接口定义的常量,而且必须实现接口中定义的所有方法;方法的声明必须和接口中完全一致
4.接口和类之间的关系
5.例子
package jiekou;
public abstract class Anilmal {
private String name;
private int age;
public Anilmal(String name, int age) {
this.name = name;
this.age = age;
}
public Anilmal() {
}
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();
//游泳不能写在父类当中
}
//接口
package jiekou;
public interface Swim {
public abstract void swim();
}
package jiekou;
public class Frog extends Anilmal implements Swim{
public Frog(String name, int age) {
super(name, age);
}
public Frog() {
}
@Override
public void eat() {
System.out.println("青蛙在吃虫");
}
@Override
public void swim() {
System.out.println("青蛙在蛙泳");
}
}
6.JDK8以后接口中新增的方法——默认方法
允许接口中定义默认方法,需要关键字default修饰——解决接口升级的问题
格式:public default 返回值类型 方法名( 列表){} public是默认的,也可以不写
注意事项:
默认方法不是抽象方法,是具有方法体的普通方法,所有继承这个接口的类都可以直接使用该方法,不强制被重写,但是如果被重写,重写的时候去掉default关键字;
如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写
并且通过这个类对象访问这个方法时,调用的就是这个重写后的方法
7.JDK8以后接口中新增的方法——静态方法
允许接口中定义静态方法,需要关键字static修饰
格式:public static 返回值类型 方法名(参数列表){}
注意事项:
静态方法只能通过接口名调用,不能通过实现类名或者对象名调用(静态方法不能被重写)
不能被实现接口的类或者子接口继承
public可以省略,static不可以省略(如果省略了会把它当成抽象方法)
8.JDK9以后接口中新增的方法——私有方法
只为接口提供服务,不需要外类访问
a.格式:private 返回值类型 方法名(参数列表){} 给默认方法使用
b.格式:private static 返回值类型 方法名(参数列表){} 给静态方法使用
9.接口的应用
a.接口代表规则,是行为的抽象,想让那个类拥有一个行为,就让这个类实现对应的接口就可以了
b.当一个方法的参数是接口的时候,可以传递接口所有实现类的对象——接口多态
10.接口和抽象类的区别
接口中所有的方法都是抽象的,而接口类可以定义带有方法体的不同方法;
一个类可以实现多个接口,但只能继承一个抽象父类;
接口和实现他的类不构成类的继承体系,即接口不是类体系中的一部分,因此不相关的类也可以实现相同的接口
三、适配器设计模式
解决接口与接口实现类矛盾问题
当一个接口中抽象方法太多,但是我们只需要使用其中一部分,就可以设计适配器模式
书写步骤:
编写中间类XXXAdapter,实现对应的接口
对接口中的抽象方法进行空实现
让真正的实现类继承中间类,并重写需要用的方法
为了避免其他类创建适配器类的对象,中间的适配器类用abstract进行修饰
(中间类继承父类,调用接口,然后子类再继承中间类)