接口的定义及使用


接口与抽象类相比,接口的使用频率是最高的,所有的设计都是围绕着接口进行的。

接口的基本概念

接口是一种特殊的类,但是在接口里面的组成与类不同,比类的组成部分简单,主要有抽象方法和全局常量所组成。而接口使用interface关键字来定义。
范例:定义一个接口

interface A{//定义一个接口
	public static final String MSG = "Hello World.";
	public abstract void print();
}

当一个接口定义完成之后,需要遵循如下的步骤进行接口的使用:

  • 接口一定要定义子类,子类利用implement关键字来实现接口,一个子类可以同时实现多个接口;
  • 接口的子类(如果不是抽象类) 必须覆写接口中的全部抽象方法;
  • 接口的对象利用子类对象的向上转型进行实例化操作。
    范例:使用接口
interface A{//定义一个接口
	public static final String MSG = "Hello World.";
	public abstract void print();
}
interface B{
	public abstract void fun();
}
class X implements A,B{//此时的X子类同时实现了A和B两个父接口
	public void print(){
		System.out.println("你好,嗨皮吗?");
	}
	public void fun(){
		System.out.println(MSG);
	}
}
public class Hello{
	public static void main(String args[]){
		X x = new X();//实例化子类对象
		A a=x;//子类为父接口实例化
		B b=x;//子类为父接口实例化
		a.print();
		b.fun();
	}
}

在这里插入图片描述
范例:神奇操作

public class Hello{
	public static void main(String args[]){
		A a = new X();//X子类为父接口A实例化
		B b = (B) a;
		b.fun();
	}
}

在这里插入图片描述
B和A没有关系,可以转换的原因是因为X是两者的子类。
注意:关于接口的组成描述
接口里面在定义的时候就已经明确的给出了开发要求:抽象方法和全局常量。所以以下两种接口的定义从本质上讲是完全一样的。
在这里插入图片描述
如果在定义接口方法的时候没有使用public,那么本质上也不是default权限,而默认就是public。
一般情况下,建议定义接口时写上public,但是可以不写abstract。
程序中出现类、抽象类、接口,这几者之间的关系需要注意。
一个普通类如果要实现接口又要继承抽象类,则一定采用先extends继承抽象类,再implements实现接口。格式:

class 子类 extends 抽象类 implements 接口1,接口2,…{}

范例:观察子类多继承问题。

interface A{//定义一个接口
	public static final String MSG = "Hello World.";
	public void print();
}
abstract class B{
	public abstract void fun();
}
class X extends B implements A{//此时的X子类同时实现了A和B两个父接口
	public void print(){
		System.out.println("你好,嗨皮吗?");
	}
	public void fun(){
		System.out.println(MSG);
	}
}

另外除了以上的结构之外,一个抽象类还可以直接实现接口。
范例:抽象类实现接口

interface A{//定义一个接口
	public static final String MSG = "Hello World.";
	public void print();
}
abstract class B implements A{//这个时候抽象类有两个抽象方法
	public abstract void fun();
}
class X extends B{//此时的X子类同时实现了A和B两个父接口
	public void print(){
		System.out.println("你好,嗨皮吗?");
	}
	public void fun(){
		System.out.println(MSG);
	}
}

抽象类可以实现接口,接口不能够继承抽象类,但一个接口可以使用extends关键字继承多个父接口。
范例:接口多继承

interface A{//定义一个接口
	public void printA();
}
interface B{
	public void printB();
}
interface C extends A,B{//C是A,B的子接口
	public void printC();
}
class X implements C{
	public void printA(){}
	public void printB(){}
	public void printC(){}
}

虽然接口本身只能够有抽象方法和全局常量,但是内部的结构是不到限制的,也就是说一个接口内部可以继续定义内部类、内部抽象类、内部接口。如果一个内部接口上使用了static定义,那么这个内部接口就属于外部接口。
范例:使用static定义内部接口

interface A{
	static interface B{
		public void print();
	}
}
class X implements A.B{
	public void print(){}
}

总之对于接口的使用可以发现有如下几点:

  • 接口避免了单继承局限,一个子类可以实现多个接口;
  • 接口中的权限统一为public,方法都是抽象方法,90%的情况下接口中很少定义全局常量;
  • 所有的内部类结构都不受到定义语法的限制,static定义的内部接口就是一个外部接口。
    在这里插入图片描述

接口的实际应用——标准

在这里插入图片描述
范例:首先要定义出的就是接口

interface USB{
	public void start();
	public void stop();
}

不管什么样的USB设备只要一连接到电脑上,那么就需要默认执行固定的操作。
范例:电脑上提供有支持USB的插入点

class Computer{
	public void plugin(USB usb){
		usb.start();
		usb.stop();
	}
}

不管有多少设备,电脑的plugin()方法里面只要接收的是USB接口实例,那么操作的步骤就是固定的。
范例:定义USB子类

class Flash implements USB{
	public void start(){
		System.out.println("开始使用U盘进行操作");
	}
	public void stop(){
		System.out.println("U盘停止工作");
	}
}

范例:定义键盘

class Keyboard implements USB{
	public void start(){
		System.out.println("开始使用键盘输入信息");
	}
	public void stop(){
		System.out.println("键盘停止工作");
	}
}

现在的子类是按照严格的操作标准使用着。
范例:程序调用处

public class Hello{
	public static void main(String args[]){
		Computer c = new Computer();
		c.plugin(new Flash());//传递U盘对象
		c.plugin(new Keyboard());//传递键盘对象
	}
}

在这里插入图片描述
此时有了接口标准,即便有几千万个子类,也是可以在一个接口上使用的,所以接口是定义标准。即,接口可以连接两个不同的层。

接口的应用——工厂设计模式(Factory,背)

为什么有工厂模式?
范例:观察代码

interface Fruit{//水果
	public void eat();//吃
}
class Apple implements Fruit{
	public void eat(){
		System.out.println("吃苹果。");
	}
}
public class Hello{
	public static void main(String args[]){
		Fruit f = new Apple();
		f.eat();
	}
}

没有语法错误,但是有设计缺陷。如果现在fruit增加了一个子类,而且主类想使用这个子类。

interface Fruit{//水果
	public void eat();//吃
}
class Apple implements Fruit{
	public void eat(){
		System.out.println("吃苹果。");
	}
}
class Cherry implements Fruit{
	public void eat(){
		System.out.println("吃樱桃。");
	}
}
public class Hello{
	public static void main(String args[]){
		Fruit f = new Apple();
		f.eat();
	}
}

此时发现,如果要扩充程序却影响了客户端的执行,这样的设计非常的不合理,解决该问题可参考Java可移植性的实现原理。

  • 不可移植性:程序 → 操作系统;
  • 可移植性:程序 → JVM → 操作系统。
    范例:可以在客户端与接口之间引入一个中间层。
    面试题:请设计一个Factory程序
interface Fruit{//水果
	public void eat();//吃
}
class Apple implements Fruit{
	public void eat(){
		System.out.println("吃苹果。");
	}
}
class Cherry implements Fruit{
	public void eat(){
		System.out.println("吃樱桃。");
	}
}
class Factory{
	public static Fruit getInstance(String className){//直接取得接口实例
		if("apple".equals(className)){
			return new Apple();
		}else if("cherry".equals(className)){
			return new Cherry();
		}else{
			return null;
		}
	}
}
public class Hello{
	public static void main(String args[]){
		Fruit f = Factory.getInstance(args[0]);
		if(f!=null){
			f.eat();
		}
	}
}

在这里插入图片描述

接口的应用——代理设计模式(Proxy,背)

代理结构是一种在接口上的 应用,一个接口有一个核心的操作功能,只依靠核心的操作主题是无法完成所需要功能的,那么需要一个代理主题。代理主题完成所有的与核心主题有关的概念。
在这里插入图片描述
范例:还原代码

interface Subject{//核心操作主题
	public void get();//核心操作
}
class RealSubject implements Subject{
	public void get(){
		System.out.println("陶大爷取回了被强行霸占的1.5亿。");
	}
}
class ProxySubject implements Subject{
	private Subject subject;//代理的真是主题
	public ProxySubject(Subject subject){
		this.subject = subject;
	}
	public void prepare(){
		System.out.println("【追逃前的准备】");
	}
	public void get(){
		this.prepare();
		this.subject.get();//真实主题的讨债
		this.destory();
	}
	public void destory(){
		System.out.println("【追逃后的收尾】");
	}
}
public class Hello{
	public static void main(String args[]){
		Subject sub = new ProxySubject(new RealSubject());
		sub.get();
	}
}

抽象类与接口的区别(面试题)

抽象类、类、对象和接口之间的关系
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
通过以上的几点比较可以发现,抽象类与接口实际上都可以限制子类必须要覆写的方法要求,但是由于抽象类本身存在有单继承局限,所以在日后开发过程之中,如果发现抽象类与接口都可以同时使用的时候,优先考虑接口,而抽象类在实际应用中,往往是作为接口与普通类之间的过渡使用的。

总结

  1. 接口利用interface关键字定义,接口中定义方法的情况居多;
  2. 接口利用对象的向上转型实现对象的实例化操作,调用的方法是每个子类所覆写的方法;
  3. 接口应用:标准(连接不同的两种类)、工厂设计模式、代理设计模式。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值