2010-05-11 54 views
0

在Ruby中,似乎有很多要挾的()的幫助下,可以通過在Ruby中,coerce()方法是否知道需要幫助強制的操作符?

def coerce(something) 
    [self, something] 
end 

那就是,當需要

3 + rational 

,Fixnum對象3做不知道如何處理增加一個理性的,所以它要求幫助的Rational#要挾通過調用rational.coerce(3),這種要挾實例方法會告訴來電者:

# I know how to handle rational + something, so I will return you the following: 
[self, something] 
# so that now you can invoke + on me, and I will deal with Fixnum to get an answer 

那麼,如果最OPE老師可以使用這種方法,但不是當它是(a - b)!=(b - a)的情況?可以強迫()知道它是哪個運算符,並且僅僅處理這些特殊情況,而僅僅使用簡單的[self,something]來處理所有其他情況,其中(a op b)==(b op a)? (op是運營商)。

+1

爲什麼要問上'coerce' _three_問題,當我與你提供在你的第一個答案? – 2010-05-11 05:53:25

+0

我從以前的帖子中獲得了很多見解。這次我想看看是否可以通過交換操作數來讓新類處理所有新操作,看到操作符是否正確,並且只處理交換不正常的情況。 – 2010-05-11 09:16:02

回答

1

coerce的目的不是要知道你試圖執行什麼操作。它的目的是使論點和self達成共識。另外,相同的操作符可以在某些類中交換,而不是其他類(例如Numeric#+Array#+),所以基於小型交換的coerce漏洞實際上並不會帶來回報。

而是推你coerce做它沒有打算,你應該創建一個新的類,而不是(如ScalarPoint,例如),並用它來對接標值與您Point

class ScalarPoint 
    attr_reader :val 

    def initialize(val) 
    @val = val 
    end 

    def +(arg) 
    case arg 
    when Point: 
     Point.new(@val + arg.x, @val + arg.y) 
    when ScalarPoint: 
     ScalarPoint.new(arg.val + @val) 
    else 
     raise "Unknown operand!" 
    end 
    end 

    # define other operators, such as * etc 

    def coerce(arg) 
    return [ScalarPoint.new(arg), self] if arg.is_a?(Numeric) 
    raise "Can't handle" 
    end 
end 

class Point 
    def coerce(arg) 
    [ScalarPoint.new(arg), self] if arg.is_a?(Numeric) 
    raise "Can't handle" 
    end 
end 

等(注:代碼未測試)

+0

如果沒有共同點,該怎麼辦?就我而言,我有一個'Money'類,我想要'Money + Money = Money'和'Numeric * Money = Money',但不是'Money * Money = Money',而不是'Numeric + Money = Money'。我該怎麼辦? – 2016-01-13 14:23:54

+0

然後'脅迫'根本不適合你。 '*'是一個左側對象的方法,它應該保持如此(不僅僅是顛倒操作數)。想想這個:爲什麼在普通的Ruby中,''a'* 3'起作用,而'3 *'a''不起作用?無論這種方式濫用「強制」會有多誘人,它根本就不是它的重點。如果你需要'Numeric * Money = Money',你需要在'Numeric'中進行,而不是在'Money'中。 – 2016-01-14 15:36:32

1

回答這個問題,你可以通過看着回溯知道操作者,但你不應該做。

這不是如何設計Ruby的強制機制。正如我在your previous question回答,coerce應返回兩個等效值[a, b],使a.send(operator, b)將工作,無論操作員。

+0

實際上,我是爲什麼脅迫必須返回2個操作數,然後讓調用者在第一個返回的元素上調用操作符?強制使用操作數和操作符(例如「+」或「*」)並使脅迫函數處理所有計算並返回1值是否同等可行或更好? – 2010-05-11 09:20:33

+0

是的,我只是覺得coerce()返回[self,other]是實現coerce()的一個非常方便的方法,但顯然它不適用於所有情況。但如果有一堂課,我們允許100(80,80),允許3 *(80,80),但不允許(3,3)*(80,80)?在這種情況下,強制函數需要返回兩個Point對象,並調用其上的「*」,該類不允許。 – 2010-05-11 09:27:23

+0

請閱讀我對上一個問題的回答。它會告訴你,你可以返回一個臨時包裝器(比如Point :: Scalar),它將以你想要的方式處理操作符。 – 2010-05-11 15:40:17