作者dasea (植栽鸡肉饭)
看板ncyu_phyedu
标题[讨论] 介面
时间Sat Jan 30 14:57:36 2010
为甚麽Java提供Interface
虽然程式语言提供了基本资料型别,但由於各种应用都有其特定的资料结构需求,因此程式
语言都提供使用者自订型别的能力。型别自订後,其使用的方法和基本资料型态类似。
Class就是一种使用者自定的型别。Java提供了instanceof的保留字,用以判断某
reference所指到的物件,其型态和某Class是否相容:
Object ref;
ref = new Bird();
if (ref instanceof Animal) { // correct
System.out.println("ref is currently pointing to an Animal Object.");
}
在物件导向的观念里,物件可以具有多个型别。例如「附有橡皮擦的铅笔」,可以当成是「
书写工具」,也可以当成是「擦拭工具」。物件可有多种型别的观念,不仅在日常生活中常
见,在软体开发上也有实际的需求。要使物件具有多种型别,可透过继承来达成。例如Bird
物件就同时具有Bird和Animal两种型别。由於Java的Class只能有单一继承,因此像「附有
橡皮擦的铅笔」同时具有「书写工具」和「擦拭工具」两种互不相关的型别,就无法透过
Class的单一继承来达成了。
许多语言提供Class的多重继承,但Java考量诸如下面的多重继承问题,选择不引进Class多
重继承:
假设B继承A,C继承A,D又多重继承B,C, 该语言又使用virtual function则
如果B, C都有overwrite A的methodM方法, 而A ref指到D类别的物件, 请问透过ref传递
methodM讯息时, 应该使用B还是C的methodM?
在不引进Class多重继承的前提下,为了让物件具有多种型态,Java提供了Interface(界面)
的观念。Interface可视为没有实作的自订型别,和Class用来作为Object的模板,有所不同
。Class可以宣告实作多个Interface,而Interface之间可以有多重继承。
Java有关Interface的语法
宣告Interface
public interface Listener {
double PI = 3.14149; // 同public static final
void listen(); // 同public abstract
}
public interface Runnalbe {
int PERIOD = 10;
void run();
}
public interface AnotherRun {
int PERIOD = 20;
void run();
int run(int);
}
注意上述函数宣告没有{},也就是说没有实作的意思。
Interface的继承
public interface ActionListener extends Listener {
}
public interface MultiInterface extends Listener, Runnalbe {
}
Class实作Interface的宣告
public class A implements Listener {
public void listen() {
}
}
public class B implements Listener, Runnable {
public void listen() {
}
public void run() {
}
}
public class C implements MultiInterface {
public void listen() {
}
public void run() {
}
}
public class D extends A implements Runnable, AnotherRun {
public void run() {
}
public int run(int period) {
}
}
Interface如同Class一样可以作为一种型态的宣告,因此如下的判断都是正确的
D ref = new D();
ref instanceof D; // true
ref instanceof Runnable; // true
ref instanceof AnotherRun; // true
ref instanceof A; // true
ref instanceof Listener; // true
Interface中宣告的变数具有以下特质
public。所谓Interface(界面)指的是外界观看某物件时,所能看到的表象以及沟通的管道
,因此Interface内的成员一定是public。也就是说即便宣告时没写public关键字
,Compiler也会帮我们加上去。
static。既然Interface没有实作,就不可能透过Interface产生物件。换言之,Interface
内的变数一定是属於Class,而不属於Object。
final。Interface可视为一种约定或契约,我们自然不希望里面的variable可以随便更改
。
Interface中宣告的method具有以下特质
public。同变数说明。
abstract。Interface没有实作,里面定义的method只是宣告而已。没有实作的method,在
Java里用abstract这个关键字来表达。有关abstract的详细说明,请见下一节
当Interface继承多个Interface,或Class实作多个Interface时,如果有多个同名的函数或
变数时,应该如何处理? 例如Runnable和AnotherRun这两个界面都定义了变数PERIOD和方
法run。
相同变数名称:由於interface内的变数具有static的性质,因此使用这些变数时,必须加上
Interface的名称才行,如Runnable.PERIOD,AnotherRun.PERIOD,因此不会造成任何混淆。
相同函数名称:如果signature(参数个数,型态以及传回值型态)完全相同,则Class只要实
作一次即可,例如Runnable和AnotherRun均定义void run(),因此Class D只要实作一次就
好了。如果同名函数符合Overloading,把它们分别当成不同的method即可。如果参数完全
相同,但传回值不同,则违反了Overloading的原则,会产生Compile Error。
Abstract Class and Method
只有参数宣告,没有实作的方法,称为abstract method。某些情况下,虽然有实作,但我们
希望强迫子类别必须override该方法时,也可以宣告为abstract method。Interface里的
方法一定没有实作,因此必然为abstract method。
如果Class里有一个以上的abstract method,则该class必须宣告为abstract。有时候即使
没有abstract method,也可以宣告该class为abstract。我们不可以直接new该class的物
件,只能new其子类别物件。
public abstract class AbstractExample {
int x;
public void abstract abstractMethod() {
}
public AbstractExample() {
x = 5;
}
}
public class SubClass extends AbstractExample {
public void abstractMethod() { // must override this method, or SubClass
be declared as abstract class
x = 10;
}
}
public class Main {
public static void main(String[] argv) {
AbstractExample a = new SubClass(); // correct
a.abstractMethod(); // virtual function, call SubClass's
abstractMethod
a = new AbstractExample(); // Compile error, you can't new abstract
class
}
}
综合以上所述,可列出以下几点特徵
具有abstract method的class必须宣告为abstract class。
继承abstract class的子类别必须override所有父类别的abstract method,否则子类别也
必须宣告为abstract class。
实作Interface A的Class必须实作A里的所有method,否则必须宣告自己为abstract class
。
不能直接new abstract class,只能new其非abstract class的子类别。
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 61.58.22.74