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?