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的特色。第一点, 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 运算子非常有用﹔个人认为第二种方法会比较好。


上一章:控制结构 目录 下一章:输入与输出