五颜六色——接口

为什么使用接口?
因为我们要一个事物可能是很多事物的组合,而java又是单继承,于是我们用接口来实现“多继承”

接口

//接口的定义
public interface MyInterface {
//使用interface关键字定义接口
//接口的名字,命名规则同类名一样
//和抽象方法一样,没有方法体
    public void foo()//其他方法
}

//接口可以当做类型定义变量
MyInterface obj;
//接口可以用instanceof运算
if (obj instanceof MyInterface) {
}

接口的特点

  1. 接口中所有方法都是public和abstract的,不能实现方法体
  2. 接口不可以被直接实例化,但可以被当做类型使用
  3. 实现类必须实现接口的所有方法
  4. 抽象类可以不实现接口的方法
  5. 一个实现类可以实现多个接口,这是Java中多继承的实现方法
  6. 接口中可以定义变量,并且变量自动是静态的

如何使用接口

//编码实现USB接口和周边

//编写接口 
public interface UsbInterface {
    /**
     * USB接口提供服务。
     */
    void service();
}

//实现接口 
public class UDisk implements UsbInterface {
//多个接口使用“,”分隔 
    public void service() {
        System.out.println("连接USB口,开始传输数据。");
    }
}

//使用接口 
UsbInterface uDisk = new UDisk();
uDisk.service();

接口的命名一般以形容词表示,多半以able结尾表示能力

面向接口编程

  • 关心实现类有何能力,而不关心实现细节
  • 面向接口的约定而不考虑接口的具体实现

接口是一种has a的关系(强调事物拥有多个功能,注意和多态的is a的关系进行区别)

Cloneable接口

  • 该接口是一个空接口,仅仅表示一种能力、一种约定
  • 所有需要复制的对象必须继承该接口,否则会有CloneNotSupportedException异常抛出
  • 所有调用clone()方法的程序都必须处理CloneNotSupportedException异常
public Object clone() throws CloneNotSupportedException {
	return super.clone();
}

深拷贝vs浅拷贝

public class MyWrapperObject implements Cloneable{
	private MyObject myObj;
	private double value;
	……
	public Object clone() {
		Object obj = null;
		try {
			obj = super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return obj;
	}
}


MyWrapperObject mwo = new MyWrapperObject(10.4, 3);
Object obj = mwo.clone();
if(obj != null) {
	MyWrapperObject another = (MyWrapperObject) obj;
			
	System.out.println(another == mwo);
	System.out.println(another.getMyObj() == mwo.getMyObj());
	another.getMyObj().setValue(6);
	mwo.getMyObj().setValue(7);
	System.out.println(another.getMyObj().getValue() + ", " + mwo.getMyObj().getValue());
} else {
			System.out.println("对象克隆失败!");
}
public Object clone() {
		……
		obj = super.clone();
		if(obj != null) {
			MyWrapperObject mwo =(MyWrapperObject) obj;
			Object aObj = myObj.duplicate();
			if(aObj != null) {
				MyObject aMyObj = (MyObject) aObj;
				mwo.myObj = aMyObj;
			}
		}
		return obj;
	}
MyWrapperObject mwo = new MyWrapperObject(10.4, 3);
Object obj = mwo.clone();
if(obj != null) {
	MyWrapperObject another = (MyWrapperObject) obj;
			
	System.out.println(another == mwo);
	System.out.println(another.getMyObj() == mwo.getMyObj());
	another.getMyObj().setValue(6);
	mwo.getMyObj().setValue(7);
	System.out.println(another.getMyObj().getValue() + ", " + mwo.getMyObj().getValue());
} else {
			System.out.println("对象克隆失败!");
}

总结
C++支持多重继承,因此没有接口的概念(也因此引起了很多的麻烦)

Java中的接口

  • 属性全都是全局静态常量
  • 方法都是全局抽象方法
  • 无构造方法

一个类可以实现多个接口,非抽象类实现接口时必须实现接口中的全部方法

抽象类利于代码复用,接口利于代码维护

更多推荐

Java编程入门笔记(九)