在我们的日常开发汇中,抽象类和接口是高频使用的,它们之间的区别也是面试必考点,下面我们来具体分析这两者有什么区别。
抽象类
- 抽象类,用来表示一个抽象概念.
- 是一种只能定义类型,而不能产生对象的类,所以定义了抽象类则必须有子类的出现.
- 抽象类的好处在于能够明确地定义子类需要覆写的方法
- 抽象类需要使用abstract声明.
- 抽象类里可以有抽象方法,该方法特征在于:只有声明,没有实现。
以下举例说明:
抽象父类
/**
* 抽象类不能实例化
*/
public abstract class AbstractAnimal {
// protected属性,子类可以继承
protected int age = 0;
// 私有属性
private String name;
// 构造器1
public AbstractAnimal(String name) {
this.name = name;
}
// 构造器2
public AbstractAnimal(int age, String name) {
this.age = age;
this.name = name;
}
// 非抽象方法已实现,子类无需实现或者可以重写
public void eat() {
System.out.println("animal eat");
}
// 抽象方法, 非抽象子类必须实现
public abstract void sleep();
// static方法,子类可以继承
public static void breath() {
System.out.println("animal breath");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
子类(非抽象)
/**
* 继承
*/
public class Dog extends AbstractAnimal {
public Dog(String name) {
super(name);
}
// 必须实现抽象方法
@Override
public void sleep() {
System.out.println("dog sleep");
}
// 默认继承父类实现,也可以重写方法
// public void eat() {
// System.out.println("dog eat");
// }
public static void main(String[] args) {
Dog dog = new Dog("wang_cai");
dog.eat();
System.out.println("dog age:" + dog.age);
}
}
子类(抽象)
// 抽象子类
public abstract class AbstractDog extends AbstractAnimal {
public AbstractDog(String name) {
super(name);
}
public AbstractDog(int age, String name) {
super(age, name);
}
// 抽象子类, 可以实现父类的抽象方法, 也可以不实现
// @Override
// public void sleep() {
// System.out.println("AbstractDog sleep");
// }
// 抽象方法, 非抽象子类必须实现
public abstract void happy();
}
接口
接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
接口的最大特点是包含抽象的方法,实现类必须实现这些方法。
以下举例说明:
接口(底层接口)
jdk1.8后增加了default方法,接口可以自己实现default方法,实现类可以不用实现或可以重写该方法,和抽象类的非抽象方法相似。
定义的属性是全局静态变量,不能被private和protected修饰。
/**
* 接口
*/
public interface AnimalBehavior {
// 属性默认是public且static且final, 接口的全局属性
int age = 0;
// 默认是public修饰
void eat();
// default修改, 默认实现方法, 实现类不用实现该方法
default void sleep(){
System.out.println("animal sleep");
}
}
实现类
public class DogBehavior implements AnimalBehavior {
// 必须实现该方法
@Override
public void eat() {
System.out.println("dog eat");
}
// 默认不用实现default方法, 也可以重写
// @Override
// public void sleep() {
// System.out.println("dog sleep");
// }
public static void main(String[] args) {
DogBehavior dogBehavior = new DogBehavior();
dogBehavior.eat();
dogBehavior.sleep();
System.out.println("dog.age=" + age);
}
}
// 运行结果
dog eat
animal sleep
dog.age=0
子接口(继承底层接口)
/**
* 接口
*/
public interface TwoLegsAnimalBehavior extends AnimalBehavior {
void run();
}
实现类(实现子接口)
public class DuckBehavior implements TwoLegsAnimalBehavior {
// 实现的是继承AnimalBehavior的接口
@Override
public void eat() {
System.out.println("duck eat");
}
// 实现的是上层接口
@Override
public void run() {
System.out.println("duck two legs run");
}
// 默认不用实现default方法, 也可以重写
// @Override
// public void sleep() {
//
// }
}
区别
相同点:都是抽象的,都可以有实现方法(前提jdk1.8)(继承或实现类可以不用实现,也可以重写方法),都可以被继承。
最大不同:一个类只能继承一个抽象类(is-a),但可以实现多个接口(has-a),抽象类的属性可以私有,接口的属性只能是public且static且final,全局静态不可变属性。
接口方法和属性都是public,而抽象类可以私有;
接口是可以多继承,但是抽象类只能单一继承;
抽象类可以实现接口;
使用场景
如果需要多继承,使用接口;
模板方法设计模式是抽象类的典型应用;
抽象类主要是代码的复用,表示is-a关系;
接口主要是一种协议约定,上游不用关心底层实现。
文档信息
- 本文作者:yindongxu
- 本文链接:https://iceblow.github.io/2021/08/13/%E6%8A%BD%E8%B1%A1%E7%B1%BB-%E6%8E%A5%E5%8F%A3%E5%8C%BA%E5%88%AB/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)