參數類(parametric classes)
在Nice中有一種非常強大的特性是可以定義參數類。參數類很像C++中的模板,或者類似其它函數型語言中的模型。而針對參數類的編程有時也被稱為泛型編程。
參數類就是有參數的類,在這種情況下參數更像一種類型而不是值。你可以把參數類認為是一族相關類,這些類除了被參數化的部分以外有相同的行為和結構。參數類常被用於數據結構中。
示例3.4 簡單Java集合
class Stack{
List contents = new LinkedList();
void push(Object o){
contents.add(o);
}
//... omitted methods
public static void main(String[] args){
Stack st = new Stack();
st.push("Test");
Integer num = (Integer)st.pop(); // Runtime error
}
}
這裡有一個非常大的安全隱患。我將一個String壓棧,然後試圖將它彈入一個Integer中,這麼做會導致一個運行時錯誤。參數類能夠解決這個問題。
示例3.5 簡單Nice集合
class Stack
List
void push(T t){
contents.add(t);
}
//... omitted methods
}
void main(String[] args){
Stack
st.push("Test");
Integer num = st.pop(); // Compile time error!
}
在Nice版的集合中,我們有一個T類型的參數類Stack。其實Stack
接口聲明
Nice和Java或C#一樣只允許單繼承,這意味著任何類只能從一個超類繼承。有時候,一個類從兩個(或更多)類“繼承”,從它的每個父類獲得行為和數據,這樣可能會更好。在Nice中,這種情況可以像Java一樣用接口去實現。
接口聲明時就像類一樣,只是接口只能包含方法,而不能包含數據成員。而和Java所不同的是,Nice中的接口也可以包含方法的默認實現,這樣就比Java中的接口更方便。
雖然說了這麼多還是以Java的模式來認識接口。在Nice中一個接口並不真正地包含任何東西,它只是一種標記。就像java.io.Serializable接口,只是一個標記,用來告知Java可以對一個類的實例進行序列化。Nice中所有的接口都是標記,這是因為Nice中擁有多元方法。多元方法由自己本身定義,而不包括在任何類或接口中。可以隨時向接口中添加新方法,就像可以隨時向類添加新方法一樣。Nice基於多元方法的另一個結果是接口不光可以“包含”方法簽名,還可以“包含”方法的具體實現。
Nice可以使用像Java一樣的方式定義接口,就像下面的例子:
示例3.6 定義接口
interface Component{
String getID();
(int,int) getPosition();
(int,int) getDimensions();
int getArea(){
(int width, int height) = this.getDimensions();
return width * height;
}
}
當然,可以等價地使用下面這種方法定義接口:
示例3.7 在接口定義中包含全局方法
interface Component {}
String getID(Component comp);
(int,int) getPosition(Component comp);
(int,int) getDimensions(Component comp);
int getArea(Component comp){
(int width, int height) = comp.getDimensions();
return width * height;
}
事實上,混合這兩種形式完全沒有問題,方法可以一些定義在接口塊(block)內,另一些定義在接口塊外。一種較好的做法是將沒有默認實現的方法定義在接口內,而有默認實現的定義在接口外。這樣當其他人閱讀代碼時會很清楚地知道實現一個接口時那些方法必須被實現。當然,編譯器會保證所有必需的方法都被實現,所以以上的內容只是一個建議。
枚舉類
枚舉類(或簡稱為enum),是一組相關的常量。許多語言支持定義簡單的常量,當然Nice也不例外。許多程序中使用了一些數字常量以表示特殊的含義。比如一個自動販賣機的程序中的一個方法會像下面這樣:
let int NICKEL = 5;
let int DIME = 10;
let int QUARTER = 25;
class VendingMachine{
int change = 0;
}
void addCoin(VendingMachine Machine, int cents){
Machine.change += cents;
}
但這個方法並不安全!它可以接受任何數量的零錢,包括一些像3或234320這樣的荒謬的數字。一種處理這個問題的方法是在運行時做檢查以確保數據時可以被接受的,並在遇到不可接受的數據時拋出異常。然而,在Nice中有一種更簡單的解決方案:枚舉。
enum class-name[(parameter-type parameter-name, ...)]{
option,...
}
枚舉可以像下面這種簡單的符號:
enum Color { Red,
Orange
, Yellow, Blue, Indigo, Violet }
或者他們可以包含整型(或其它)的值:
enum VendingCoin(int value){
nickel(5), dime(10), quarter(25);
}
class VendingMachine{
int change = 0;
}
void addCoin(VendingMachine Machine, VendingCoin cents){
Machine.change += cents.value;
}
當然,一台真正的自動販賣機會保留每一種硬幣的實際數量,而不僅僅時它們的總和!