2014-09-01 83 views
0

假設我已經實現了一個Vector類。在C++中,可以通過在全局範圍內重載operator *做自然的數學表達式「縮放」:浮動倍數紅寶石矢量

template <typename T> // T can be int, double, complex<>, etc. 
Vector operator*(const T& t, const Vector& v); 
template <typename T> // T can be int, double, complex<>, etc. 
Vector operator*(const Vector& v, const T& t); 

然而,當它去紅寶石,因爲參數沒有輸入,就可以寫

class Vector 
    def *(another) 
    case another 
    when Vector then ... 
    when Numeric then ... 
    end 
    end 
end 

這允許Vector * Numeric而不是Numeric * Vector。有解決它的方法嗎?

回答

2

[使用Numeric,而不是我的答覆Numerical]

做到這一點的最普遍的方式是將coerce方法添加到Vector。當Ruby遇到5 * your_vector時,對5.*(your_vector)的調用失敗,它將調用your_vector.coerce(5)。您的coerce方法將返回兩個項目,*方法將重試這些項目。

從概念上講,這樣的事情5.*(your_vector)失敗後會發生:

first, second = your_vector.coerce(5) 
first.*(second) 

最簡單的方法是傳回your_vector作爲第一個項目,5作爲第二。

def coerce(other) 
    case other 
    when Numeric 
    return self, other 
    else 
    raise TypeError, "#{self.class} can't be coerced into #{other.class}" 
    end 
end 

這適用於交換操作,但不適用於非交換操作。如果你有一個簡單的,自包含的程序,只需要*工作,你可以擺脫它。如果你正在開發一個圖書館或需要更多的東西通用的,是有意義的轉變5Vector,你可以做,在coerce

def coerce(other) 
    case other 
    when Numeric 
    return Vector.new(other), self 
    else 
    raise TypeError, "#{self.class} can't be coerced into #{other.class}" 
    end 
end 

這是一個更強大的解決方案,如果它使語義感。如果它沒有語義意義,您可以創建一箇中間類型,您可以將其轉換爲Numeric,該類型確實知道如何與Vector相乘。這the approach that Matrix takes

作爲最後的手段,你可以拉出來的大槍和使用alias_method重新定義*Numeric處理Vector。我不打算爲這種方法添加代碼,因爲做錯了會導致災難,並且我沒有想過涉及任何邊界案例。