Nice用戶手冊(四)
2024-07-21 02:14:12
供稿:網(wǎng)友
參數(shù)類(parametric classes)
在nice中有一種非常強(qiáng)大的特性是可以定義參數(shù)類。參數(shù)類很像c++中的模板,或者類似其它函數(shù)型語言中的模型。而針對參數(shù)類的編程有時也被稱為泛型編程。
參數(shù)類就是有參數(shù)的類,在這種情況下參數(shù)更像一種類型而不是值。你可以把參數(shù)類認(rèn)為是一族相關(guān)類,這些類除了被參數(shù)化的部分以外有相同的行為和結(jié)構(gòu)。參數(shù)類常被用于數(shù)據(jù)結(jié)構(gòu)中。
示例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中,這么做會導(dǎo)致一個運行時錯誤。參數(shù)類能夠解決這個問題。
示例3.5 簡單nice集合
class stack<t>{
list<t> contents = new linkedlist();
void push(t t){
contents.add(t);
}
//... omitted methods
}
void main(string[] args){
stack<string> st = new stack();
st.push("test");
integer num = st.pop(); // compile time error!
}
在nice版的集合中,我們有一個t類型的參數(shù)類stack。其實stack<t>是一種給編譯器的信號,它告訴編譯器如何創(chuàng)建一個用于給定類型的stack。當(dāng)編譯器得知我們只會把string放到這個棧中時,任何企圖從stack<string>中取出一個integer的代碼都會導(dǎo)致編譯器報錯。
接口聲明
nice和java或c#一樣只允許單繼承,這意味著任何類只能從一個超類繼承。有時候,一個類從兩個(或更多)類“繼承”,從它的每個父類獲得行為和數(shù)據(jù),這樣可能會更好。在nice中,這種情況可以像java一樣用接口去實現(xiàn)。
接口聲明時就像類一樣,只是接口只能包含方法,而不能包含數(shù)據(jù)成員。而和java所不同的是,nice中的接口也可以包含方法的默認(rèn)實現(xiàn),這樣就比java中的接口更方便。
雖然說了這么多還是以java的模式來認(rèn)識接口。在nice中一個接口并不真正地包含任何東西,它只是一種標(biāo)記。就像java.io.serializable接口,只是一個標(biāo)記,用來告知java可以對一個類的實例進(jìn)行序列化。nice中所有的接口都是標(biāo)記,這是因為nice中擁有多元方法。多元方法由自己本身定義,而不包括在任何類或接口中??梢噪S時向接口中添加新方法,就像可以隨時向類添加新方法一樣。nice基于多元方法的另一個結(jié)果是接口不光可以“包含”方法簽名,還可以“包含”方法的具體實現(xiàn)。
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;
}
}
當(dāng)然,可以等價地使用下面這種方法定義接口:
示例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)內(nèi),另一些定義在接口塊外。一種較好的做法是將沒有默認(rèn)實現(xiàn)的方法定義在接口內(nèi),而有默認(rèn)實現(xiàn)的定義在接口外。這樣當(dāng)其他人閱讀代碼時會很清楚地知道實現(xiàn)一個接口時那些方法必須被實現(xiàn)。當(dāng)然,編譯器會保證所有必需的方法都被實現(xiàn),所以以上的內(nèi)容只是一個建議。
枚舉類
枚舉類(或簡稱為enum),是一組相關(guān)的常量。許多語言支持定義簡單的常量,當(dāng)然nice也不例外。許多程序中使用了一些數(shù)字常量以表示特殊的含義。比如一個自動販賣機(jī)的程序中的一個方法會像下面這樣:
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;
}
但這個方法并不安全!它可以接受任何數(shù)量的零錢,包括一些像3或234320這樣的荒謬的數(shù)字。一種處理這個問題的方法是在運行時做檢查以確保數(shù)據(jù)時可以被接受的,并在遇到不可接受的數(shù)據(jù)時拋出異常。然而,在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;
}
當(dāng)然,一臺真正的自動販賣機(jī)會保留每一種硬幣的實際數(shù)量,而不僅僅時它們的總和!