Java8——抽象类+接口
定义语法:
普通类可以直接产生实例化对象,并在普通类中可以包含有构造方法,普通方法,static方法、常量,变量;抽象类就是在普通类的机构里面增加抽象方法的组成部分。
抽象方法没有方法体{},并且抽象方法必须使用 abstract 关键字进行定义。
abstract class A{ //定义一个抽象类
public void fun(){ //普通方法
System.out.printIn("存在有方法体的方法!");
}
//此方法体没有方法体的声明,并且存在abstract关键字,表示抽象方法
public abstract void print();
}
对抽象类的使用原则如下:
- 抽象类必须有子类,即:每一个抽象类一定要被子类继承;
- 抽象类的子类(子类不是抽象类)必须要覆写抽象类中的全部抽象方法(强制子类覆写)
- 抽象类的对象实例化需要依靠子类完成,采用向上转型的方式处理;
抽象类与普通类对比:
- 抽象类继承子类里面会有明确的方法覆写要求,而普通类没有;
- 抽象类只比普通类多了一些抽象方法定义,其他组成部分与普通类完全一致;
- 普通类可以直接实例化,但是抽象类的对象必须经过向上转型之后才可以得到实例化对象;
虽然子类可以继承任意一个普通类,但是在开发的角度上,普通类不要去继承一个普通类,而只能去继承一个抽象类。
抽象类的相关限制:
抽象类里面有一些属性,抽象类存在构造方法,目的:为属性初始化,子类初始化的时候依然满足先执行父类构造,再执行子类构造的情况;
- 抽象类不可以用 final 因为抽象类必须有子类,而 final 定义的类不能有子类;
- 外部的抽象类不允许使用 static 声明,而内部的抽象类允许使用 static 声明;用 static 声明的内部抽象类就相当于一个外部抽象类,继承的时候使用 " 外部类.内部类 "的形式表示类名称;
- 任何时候,想执行类中的 static 方法的时候,都可以在没有对象的时候直接调用,对抽象类也是一样;此时可以没有子类。
接口的定义:
如果一个类只是由抽象方法和全局常量所组成,那么这种情况下,不会将其定义为一个抽象类,而只会定义为接口,所以接口严格意义上来讲,属于一个特殊的抽象类,而且这个类里面只有抽象方法与全局常量(连构造都没有);
要定义一个接口使用 interface 完成;
interface A{ //接口
public static final String MSG = "Hello"; //全局常量
public abstract void print(); //抽象方法
}
接口里面有 static 方法,所以接口对象不可能直接使用关键字 new 直接实例化操作;接口的使用原则:
- 接口必须要有子类,但是此时一个子类可以使用 implements 关键字实现多个接口;
- 接口的子类(如果不是抽象类),必须覆写接口中全部的抽象方法;
- 接口对象可以利用子类对象的向上转型进行实例化操作;
对于子类而言,除了接口之外,可能还会继承抽象类,所以既需要继承抽象类,又需要实现接口的话,那么先使用 extends 继承,再使用 implements 实现接口类;
interface A{ //接口
String MSG = "Hello"; //全局常量
void print(); //抽象方法
}
在接口里面没有写上 public ,其最终访问权限也是 public,绝对不是default;但是最好加上 public!
一个抽象类可以继承一个抽象类,但是一个接口可以利用 extends 关键字同时继承多个接口(接口不能继承抽象类);
从继承关系上讲,抽象类的限制要比接口多很多:
- 一个抽象类只能继承一个抽象的父类,但是接口没有这个限制;
- 一个子类只能继承一个抽象类,但却可以实现多个接口;
在整个Java里面,接口的主要功能是解决单继承局限问题;
先期总结:接口在实际开发中有三大核心作用:
- 定义不同层之间的操作标准;
- 表示一种操作能力;
- 表示将服务器中的远程方法视图暴露给客户端;
接口的应用——工厂设计模式:
interface Fruit{
public static void eat();
}
class Apple implements Fruit{
public void eat(){
System.out.printIn("****吃苹果");
}
}
class Orange implements Fruit{
public void eat(){
System.out.printIn("****吃橘子");
}
}
class Factory {
public static Fruit getInstance (String className){
if("apple".equals(className)){
return new Apple();
}else if("orange".equals(className)){
return new Orange();
}else {
return null;
}
}
}
publlic class TestDemo{
public static void main(String args[]){
Fruit f = Factory.getInstance("apple");
f.eat();
}
}
接口的应用——代理设计模式:
interface Subject{
public void make(); //整个临幸的核心功能
}
class RealSubject implements Subject{
public void make(){
System.out.printIn("皇上正在XXX");
}
}
class ProxySubject implements Subject{ //内官
private Subject subject;
//接收一个真正主题的操作对象
public ProxySubject(Subject subject){
this.subject = subject;
}
public void prepare(){
System.out.printIn("内官的准备工作");
}
public void make(){
this.prepare();
this.subject.make(); //告诉皇上可以开始了
this.destroy();
}
public void destroy(){
System.out.printIn("内官的收尾工作");
}
}
public class TestDemo{
public static void main(String args[]){
Subject sub = new ProxySubject(new RealSubject()); //用户只能看见Subject
sub.make(); //调用的代理主题操作,由代理主题操作完成真实主题操作,
}
}
代理模式的核心:有一个主题的操作接口(可能有多种方法),核心业务主要完成核心内容;而代理主题负责完成所有与核心主题有关的操作;
抽象类与接口类的区别:
区别 | 抽象类 | 接口类 |
关键字 | abstract class | interface |
组成 | 构造方法、普通方法、抽象方法、static方法、常量、变量 | 抽象方法、全局常量 |
子类使用 | class 子类 extends 抽象类 | class 子类 implements 接口,接口… |
关系 | 抽象类可以实现多个接口 | 接口不能继承抽象类,却可以继承多个父接口 |
权限 | 可以使用各种权限 | 只可以使用public权限 |
限制 | 单继承局限(一个子类只能继承一个抽象类) | 没有单继承局限 |
子类 | 抽象类和接口都必须有子类,子类必须覆写全部的抽象方法; | |
实例化对象 | 依靠子类对象的向上转型进行对象的实例化 |
抽象类比接口支持的功能更多,但是单继承特性掩盖了抽象类的优点,即:当抽象类和接口都可以使用的时候,优先使用接口;
参考:
- 在进行某些公共操作的时候一定要定义接口;
- 有了接口需要利用子类完善方法;
- 如果是自己写的接口,不要用 new 直接实例化接口,而是使用工厂类完成;
上一篇: 【从零写javaweb框架】(三)开发一个类加载器
下一篇: Java接口和抽象类区别