BOO大全/值型别
值型别
[编辑]在 CLI 程式里,正如前面所讨论的,有两种类型的值。在数值运算式里,值会被复制,而不是参考。对数值来说,复制是个廉价的动作,因为只需要复制几个 bytes。通常你不会想要在物件上做相同的动作,不过有时候的确有必要在某些型别这样作,这时候就可以考虑将该型别定义为 struct。
struct Point3D:
public X as double
public Y as double
public Z as double
def constructor(x as double, y as double, z as double):
X = x; Y = y; Z = z
def Add(p as Point3D):
return Point3D(X + p.X, Y + p.Y, Z + p.Z)
override def ToString():
return "(${X},${Y},${Z})"
p1 = Point3D(10.0,20.0,30.0)
p2 = Point3D(1.0,1.0,2.0)
print p1,p2,p1.Add(p2)
执行结果
(10,20,30) (1,1,2) (11,21,32)
运算子的覆载
[编辑]或许你会想改变 x+y 的动作。举例来说,前面提到的Point3D可以用来表现 3D 空间的向量,然后可以加上向量。加的动作应该是以数学的 + 来进行,这样更直觉 (所以也可以用在复数或矩阵上)。要为 3D 向量覆载+的话,以下列的静态方法取代原来的 Add 方法即可:
static def op_Addition(self as Point3D, p as Point3D): return Point3D(self.X + p.X, self.Y + p.Y, self.Z + p.Z)
这儿有两件事情要提醒,必须是静态方法,而且要使用运算子的内部名称。
当你进行覆载时,最好也针对所有相关的数值运算作覆载。如果你覆载了"加",你必须也覆载"减"与一元运算的"减"﹔如果你覆载了"乘",你必须也覆载"除"。
这些是你可以覆载的运算名称(此处以 Boo 0.7.5 为准):
- op_Addition +
- op_Subtraction -
- op_Multiply *
- op_Division /
- op_Modulus %
- op_Exponentiation **
- op_Equality ==
- op_LessThan <
- op_LessThanOrEqual <=
- op_GreaterThan >
- op_GreaterThanOrEqual >=
- op_Match =~
- op_NotMatch not =~
- op_Member in
- op_NotMember not in
- op_BitwiseOr |
- op_BitwiseAnd &
- op_UnaryNegation -
因为 x+=y 相等于 x=x+y,覆载 + 会自动覆载 +=。But,OverloadInPlaceAddition(译注:难以翻译,保留原文)。
如果你无法肯定是否要覆载的话,就不要覆载。这是很危险的,因为你正在发明新的表示方法,而这可能会使其他人困扰,并使你的程式难以理解。举例来说吧,add 并不一定是加,像加入一个 customer 到 customer 串列时,就不应该去覆载+,因为这样的动作并没有产生新串列,不应该让 + 有不同的语意(译注:因为覆载以后,通常需要传回新物件,看看上面的例子。)。
OverloadInPlaceAddition
[编辑]It would probably be useful to allow binary operations like InPlaceAddition to be overloaded directly, because just relying on the usual x += y ==> x = x + y leads to potentially inefficient code for value types.
The question is, why restrict overloading at all?