接口 (Java)
此条目包含过多行话或专业术语,可能需要简化或提出进一步解释。 (2013年1月19日) |
介面(英语:Interface),在Java程式语言中是一个抽象型别(Abstract Type),它被用来要求类别(Class)必须实作指定的方法,使不同类别的物件可以利用相同的界面进行沟通。介面通常以interface
来宣告,它仅能包含方法签名(Method Signature)以及常数宣告(变数宣告包含了 static
及 final
),一个介面不会包含方法的实作(仅有定义)。在Java 8之后,被放宽为允许定义默认方法——在接口具体实现方法,和类静态方法。
介面无法被实例化,但是可以被实作。一个实作介面的类别,必须实作介面内所描述的所有方法,否则就必须宣告为抽象类别(Abstract Class)。另外,在Java中,介面型别可用来宣告一个变数,他们可以成为一个空指标,或是被绑定在一个以此介面实现的物件。
其中一个使用介面的优势是,可以利用他们模拟多重继承,类别在JAVA中不允许多重继承,所有在JAVA中的类别必须而且仅能有一个父类别,而java.lang.Object
(JAVA型别系统中最顶层的型别)是唯一一个例外。
JAVA的类别可以被实作许多个介面,然而一个介面则无法实作其他的介面。
概观
介面被用来统一类别的共通行为,当不同的类别需要进行资讯共享时,是不需要特别去建立类别间的关系。举例来说,一个人(Human)及一只鹦鹉(Parrot)都会吹口哨(whistle),然而Human
及Parrot
不应该为Whistler
的子类别,最好的做法是令他们为Animal
的子类别,而他们可以使用Whistler
的介面进行沟通。
还有一种介面的使用方法,则是当一个物件有实现特定介面时,我们使用它是不需要知道它的类别,例如,一个事物因为口哨的噪音影响到其他人,对于其他人而言,就不需要知道噪音来源是来自人还是鹦鹉,因为他们可以确定,一个会吹口哨的事物正在吹口哨。举一个更实际的例子,排序算法可能会期待物件的型别是可以被Comparable
的,于是它只需要知道物件的型别可以被以某种方式进行排序即可,这与物件的类别无关。whistler.whistle()
将会呼叫物件的实现方法whistle
,而不需要知道物件是以哪个类别来实现Whistler
。
例如:
interface Bounceable {
void setBounce(); // 注意分號
// 介面的方法(method)是公開(public)、抽象(abstract)、永遠不會是最尾端的型別(final)
// 把它們想成只是個模型,所以沒有任何方法有被實現
//以下语法在Java 8之后的版本是可行的,之前则编译错误
default void defaultMethod(){
System.out.println("defaultMethod");
setBounce(); //可以调用同接口的实例方法
}
}
使用方法
介面的宣告
下列的语法为介面的宣告方式:
[存取修飾] interface 介面名稱 [extends 其他的介面] { 常數宣告 抽象方法宣告 }
介面的主体包含著抽象方法,但所有方法在介面内(定义上)都是抽象(Abstract)方法,所以abstract
的关键字在介面内则不被需要。由于介面代表著一个对外行为的集合,所以任何方法在介面内都是public
(公开的)。
所以,一个简单的介面可以这么写
public interface Predator {
boolean chasePrey(Prey p);
void eatPrey(Prey p);
}
介面内的成员皆为静态(static)、final及公开(public),反之,他们可以成为任何类别或介面的型别[1]
实现一个介面的语法,可以使用这个公式:
... implements 介面名稱[, 其他介面, 其他的..., ...] ...
类别可以用来实现介面,举例来说
public class Lion implements Predator {
public boolean chasePrey(Prey p) {
// programming to chase prey p (specifically for a lion)
}
public void eatPrey (Prey p) {
// programming to eat prey p (specifically for a lion)
}
}
如果一个类别实现了一个介面,而没有实现介面的所有方法,则它必须被标注为abstract
(抽象类别)。一个抽象类别的子类别必须实现它未完成的方法,假如该项子类别仍不会实现介面的所有方法,那么该项子类别依然需要被标注为abstract
。
类别可以同时实现多项介面
public class Frog implements Predator, Prey { ... }
介面通常被使用在Java程式语言,用来做回调函数使用[2] 。Java并不允许方法作为参数传递使用,因此,其中一个解决办法则是可以定义一个介面,把这个介面当成方法的参数,以此来使用该项物件的方法签名。
子介面
介面可以被延伸为数个不同的介面,可以使用上述所描述的方法,举例来说:
public interface VenomousPredator extends Predator, Venomous {
//介面主體
}
以上的程式片段是合法定义的子介面,与类别不同的是,介面允许多重继承,而Predator
及 Venomous
可能定义或是继承相同的方法,比如说kill(Prey prey)
,当一个类别实现VenomousPredator
的时候,它将同时实现这两种方法。
范例
有些泛用的Java介面可供参考:
Comparable
拥有一个方法compareTo
,用以描述两个物件是否相等,或是其中一个物件大于另外一个物件。泛型允许已经实现的类别,其物件可以用来互相比较。Serializable
是一个标记接口(marker interface),没有任何方法或是成员,仅有一个空的主体,它被用来表示一个类别可以被序列化。它的Javadoc描述了他是如何运作,而且不需要被强制编程。
另见
参考文献
- ^ The Java Language Specification. [2013-01-18]. (原始内容存档于2012-02-29).
- ^ Java World. [2013-01-18]. (原始内容存档于2008-09-16).