BOO大全/型別轉換
型別轉換
编辑某些型別可以隱性地轉換為其他型別,所以明確的轉換是醜陋且不必要的。任何數值型別可以轉換為其他數值型別。如果類別實作了某個介面,那麼以此類別產生的物件可以自動轉換為該介面型別﹔同樣的,衍生類別也是。你最好的指引就是(總是)編譯器本身。
但要當心,有些轉換編譯器會允許,可是卻只能在執行時期決定是否可行。
def one(o as object):
print 'one',o
def two(s as string):
print 'two',s
def three(n as int):
print 'three',n
one("hello")
one(42)
two("dolly")
# two(66) <= compile-time error - string doesn't cast to int.
# best overload for the method 'implicitCast1Module.two(System.String)'
# is not compatible with the argument list '(System.Int32)'
obj as object
obj = "hello dolly"
two(obj)
obj = 42
three(obj)
obj = 'hello'
three(obj) <= ok with compiler, but causes an InvalidCastException at run-time.
雖然 three 函式的引數型別為 int,但編譯器會允許讓型別為 object 的物件傳入,這是因為只有在執行時,才會知道這個物件真正的型別為何。(你可能不認同這點,認為編譯器應該要檢查﹔不過事實就是如此,請記住這點,並把它當作一個特例。)
這些靜態編譯器的錯誤順便也讓你看到幾項Boo的特色。第一點, int 是 System.Int32 的別名。第二點,單獨的函式其實是模組類別(被自動產生)裡的靜態方法。第三點,函式可以多載,這是為甚麼編譯器並非簡單地告訴你引數不相符的原因。
字串是一個參考物件,所以 null 對字串變數來說,是個很好的合法值,這也表示字串是個可為null的型別。對照簡單的值型別,像整數,它無法有個特別的值用來表示"非整數"。 0 不是一個好的候選者,因為很多有意義的整數也是 0。
在 Boo 有兩種明確進行轉換型別的方法,第一種方法適用於所有型別,但如果無法轉換時,會提出編譯或執行時期錯誤。舉例來說,一個為 object 型別的變數可能是任何型別,所以如果這個 object 變數裡不包含要求的型別時,將會提出InvalidCastException例外。
>>> s = "Hello, World!" >>> n = 10 >>> cast(double,n) (Double) 10 >>> cast(string,n) ----^ ERROR: Cannot convert 'System.Int32' to 'System.String'. >>> obj as object # declare as object (initial value null) >>> obj = "Hello, World!" >>> cast(int,obj) System.InvalidCastException: Specified cast is not valid. ....
作者:Booish 真的是個不可思議的工具,我建議你一定要使用他來學習 Boo。但有個地方可能會與編譯時的行為不同,你要特別注意,那就是 Booish 預設會將 DuckTyping 選項打開。
第二種方法是使用 as 關鍵字作為運算子。下面的範例除了示範變數宣告以外,也示範了型別轉換。
s as object = "hello dolly" ss = s as string print ss.ToUpper()
在上面的例子你也可以使用 cast,但 as 在錯誤時不會提出例外,只會回傳 null。也因此,as 不能搭配像數值等的值型別來使用。這兒有兩個例子,說明了這件事情,同樣都可以用來檢查 k 是否為整數:
k as object = 42 if (ss = k as string) != null: print ss.ToUpper() else: print "was not a string!" if k isa string: ss = (k as string).ToUpper() print ss else: print "was still not a string!"
在執行時期偵測型別時,isa 運算子非常有用﹔個人認為第二種方法會比較好。