一、接口
为什么要使用接口?
原因:抽象类与普通类相比,抽象类约定了子类的实现要求,但是抽象类存在单继承局限。如果要约定子类的实现要求并且避免单继承局限就需要使用接口。
定义:一个抽象方法与全局产量的集合(JDK8之前),使用interface关键字定义。
定义一个简单接口:
interface IMessage{
public static final String MSG = "I am a biter";//全局常量
public abstract void print();//抽象方法
}
1.接口优先原则:
一个操作既可以使用抽象类,又可以使用接口时,优先考虑接口。
2.接口的命名规范:
- 接口前加 I :区分接口与类。
- 子类实现接口:使用implements关键字,并且子类可以同时实现多个父接口(可以使用接口实现多继承)。
- 一般使用接口名+Impl来命名子类
//对于接口的子类(不是抽象类)必须覆写接口中的全部抽象方法。可以利用子类的向上转型通过实例化子类得到接口的实例化对象。
interface IMessage{
public static final String MSG = "I am a biter";//全局常量
public abstract void print();//抽象方法
}
interface INews{
public abstract String getNews();
}
class MessageImpl implements IMessage,INews{
public void print(){
System.out.println(IMessage.MSG);
}
public String getNews(){
return IMessage.MSG;//访问常量都建议加上类名称
}
}
public class Test{
public static void main(String[] args){
IMessage m = new MessageImpl();//子类向上转型,为父接口实例化对象
m.print();//调用被子类覆写的方法
INews n = (INews)m;
System.out.println(n.getNews());
}
}
运行结果:
I am a biter
I am a biter
3.接口的使用限制:
(1) 接口不能继承抽象类,可以使用extends继承多个父接口。
一个接口可以使用extends继承多个父接口
interface A{
public void printA();
}
interface B{
public void printB();
}
interface C extends A,B{//接口多继承
public void printC();
}
class Impl implements C{
public void printA(){}
public void printB(){}
public void printC(){}
}
接口定义内部结构,包括:内部普通类、内部接口。使用static定义的内部接口相当于一个外部接口。
附:使用static定义的内部接口,来描述外部接口
interface A{
public void printA();
static interface B{
public void printB();//使用static定义,描述一个外部接口
}
}
class Impl implements A.B{
public void printB(){}
}
(2) 接口中public、static、final、abstract均可以忽略。
(3) 阿里编码规约:接口中的方法和属性不加任何修饰符,public也不加,保证代码的简洁性。
(4) 当一个子类既要实现接口,又要继承抽象类时,先使用extends继承一个抽象类,再使用implements实现多个接口。
子类继承抽象类、实现接口:
interface IMessage{
public void print();
}
abstract class News{
//抽象类中的方法,前面的abstract不能省略,否则就是普通方法。
public abstract void getNews();
}
class MessageImpl extends News implements IMessage{//此时implements IMessage只是为了强调MessageImpl是IMessage的子类
public void print(){
System.out.println("I am a biter");
}
public void getNews(){
System.out.println("I am News");
}
}
public class Test{
public static void main(String[] args){
IMessage m = new MessageImpl();
m.print();
//MessageImpl是抽象类和接口的共同子类
News news = (News)m;
news.getNews();
}
}
运行结果:
I am a biter
I am News
抽象类实现接口
interface IMessage{
public void print();
}
abstract class News implements IMessage{
//News为抽象类,可以不实现IMessage中的抽象方法
public abstract void getNews();//抽象方法
}
class MessageImpl extends News{
public void print(){
System.out.println("I am a biter");
}
public void getNews(){
System.out.println("I am News");
}
}
public class Test{
public static void main(String[] args){
IMessage m = new MessageImpl();
m.print();
News news = (News)m;
news.getNews();
}
}
运行结果:
I am a biter
I am News实际上此时上述结构属于三层继承。
附:权限即使不写也是public,下图中print方法没有修饰符,比public的权限更加严格,因此不能覆写。
如果用public修饰print(),则不会报错。即可以覆写。只要是方法就用public定义。
附:接口中全局常量和抽象方法的定义
①完整格式:
interface IMessage{
public static final String MSG = "I am a biter";
public abstract void print();
}
②简化格式:
interface IMessage{
String MSG = "I am a biter";
void print();
}
由于接口之中只是全局常量和抽象方法的集合,所以上述两种定义格式效果是一样的。
注意:99%的接口只提供抽象方法。很少在接口里提供全局变量。
4.接口的应用:
(1)定义操作标准:USB2.0标准。
例:电脑上可以使用任何的USB设备(U盘、打印机等)
分析:定义一个U盘UDisk子类和打印机PrintDisk子类来分别实现USB接口中的抽象方法,来实现各自的具体操作。
interface USB{
public void setup();//安装USB驱动
public void work();//进行工作
}
//定义一个Usb设备
class UDisk implements USB{
public void setup(){
System.out.println("安装U盘驱动");
}
public void work(){
System.out.println("U盘开始工作");
}
}
//定义一个打印机设备
class PrintDisk implements USB{
public void setup(){
System.out.println("安装打印机驱动");
}
public void work(){
System.out.println("打印机开始工作");
}
}
class Computer{
public void plugin(USB usb){//只能插USB设备
usb.setup();//安装
usb.work();//工作
}
}
public class Test{
public static void main(String[] args){
Computer computer = new Computer();
computer.plugin(new UDisk());
computer.plugin(new PrintDisk());
}
}
运行结果:
安装U盘驱动
U盘开始工作
安装打印机驱动
打印机开始工作
(2)表示一种能力、进行一项操作。
(3)在分布式开发中暴露远程服务方法。