2010-05-11 40 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