跳转到内容

BOO大全/型別轉換

维基教科书,自由的教学读本
(重定向自BOO/ControlStructures

上一章:控制結構 目錄 下一章:輸入與輸出


型別轉換

[编辑]

某些型別可以隱性地轉換為其他型別,所以明確的轉換是醜陋且不必要的。任何數值型別可以轉換為其他數值型別。如果類別實作了某個介面,那麼以此類別產生的物件可以自動轉換為該介面型別﹔同樣的,衍生類別也是。你最好的指引就是(總是)編譯器本身。

但要當心,有些轉換編譯器會允許,可是卻只能在執行時期決定是否可行。

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的特色。第一點, intSystem.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 運算子非常有用﹔個人認為第二種方法會比較好。


上一章:控制結構 目錄 下一章:輸入與輸出