2010-05-11 1 views
0

, 강제 변환의 많은() 도움을 추가 처리하는 방법을 알고하지 않습니다Ruby에서 coerce() 메소드는 도움이 필요한 연산자가 무엇인지 알 수 있습니까? 루비에서

3 + rational 

이 필요하다입니다

def coerce(something) 
    [self, something] 
end 

, Fixnum이라는 3하여 수행 할 수 있습니다 보인다 이 Rational, 그것은 rational.coerce (3)를 호출하여 도움이 용 Rational #의 강제 변환을 요청하고이 강제 변환 인스턴스 방법은 호출자에게 않도록 :

# 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 경우를 rators는이 방법을 사용할 수 있지만 (a - b)! = (b - a) 상황이 아닌 경우? coerce()가 어떤 연산자인지 알고, 그 특별한 경우를 처리 할 수 ​​있으며, (a op b) == (b op a) 인 다른 모든 경우를 처리하기 위해 단순한 [self, something]을 사용하고 있을까요? (op는 연산자입니다).

+1

왜 coerce''에 _three_ 질문 첫 번째 답변에? –

+0

이전 게시물에서 많은 통찰력을 얻었습니다. 이번엔 새로운 클래스가 피연산자를 바꿔서 새로운 클래스를 처리 할 수 ​​있는지, 연산자가 그렇게하는 것이 옳은지 살펴보고, 스와핑이 올바르지 않은 경우에만 처리 ​​할 수 ​​있는지 확인하고 싶습니다. –

답변

1

coerce의 요점은 수행하려는 작업을 알 수 없습니다. 그것의 목적은 인수와 self을 공통점으로 가져 오는 것입니다. 또한 동일한 연산자는 특정 클래스에서는 교환 가능하고 다른 클래스에서는 교환 할 수 없습니다 (예 : Numeric#+Array#+). 따라서 작은 commutativity 기반 coerce 익스플로잇은 실제로 효과가 없을 것입니다. 대신이 대신 새로운 클래스를 생성 (예를 들어, ScalarPoint 등)와 함께 스칼라 값을 인터페이스를 사용해야하는 것은 아니다 무엇을 할 당신의 coerce을 밀어

당신의 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 

등 (NB : 코드를 테스트하지) 내가 당신을 제공 할 때

+0

공통 접지가 없으면 어떻게 될까요? 제 경우에는 클래스'머니'가 있는데,'머니 + 머니 = 머니'와'머니 * 머니 = 머니'가 아니라'머니 * 머니 = 머니'가 아니라 '머니 머니 = 머니' 어떻게해야합니까? –

+0

그렇다면 '강제성'은 단순히 당신을위한 것이 아닙니다. '*'는 왼쪽 객체의 메소드이며, 그렇게 유지되어야합니다 (피연산자를 더 이상 쓸모 없게 반전하는 것이 아닙니다). 생각해 보면, 왜 루비에서는 '' '* 3'이 작동하고 '3 *' '' ''이 아닌가? 어쨌든 유혹을 불러 일으키다가 '강요하다 (coerce)'를 오용하는 것은 단순히 그 요점이 아닙니다. 'Numeric * Money = Money'가 필요하면'Money'가 아닌'Numeric'에서해야합니다. –

1

이 질문에 대한 답은 역 추적을 보면 운영자를 알 수 있지만 그렇게하지 말아야한다는 것입니다.

루비의 강요 메커니즘이 어떻게 설계되었는지가 아닙니다. 내가 your previous question에 대답했을 때, coerce[a, b]과 같은 값을 반환해야합니다. a.send(operator, b)이 무엇이든 관계없이 작동합니다.

+0

실제로 궁금해, 왜 강제로 2 피연산자를 반환하고 호출자가 첫 번째 반환 된 요소에 대한 연산자를 호출 할 수 있도록해야합니까? coerce가 피연산자와 연산자 (예 : "+"또는 "*")를 사용하고 강제 계산 함수가 모든 계산을 처리하고 단 하나의 값만 반환하도록하는 것이 동등하게 가능하거나 더 나은가요? –

+0

예, 나는 [자기, 기타]를 반환하는 강제()가 강제()를 구현하는 매우 편리한 방법이지만, 분명히 모든 경우에 대해 작동하지 않는다는 인상을 받고있었습니다. 그러나 우리가 100- (80,80)을 허용하고 3 * (80,80)을 허용하지만 (3,3) * (80,80)을 허용하지 않는 수업이 있다면 어떻게 될까요? 이 경우 coerce 함수는 두 개의 Point 객체를 반환해야하며 클래스에서 허용하지 않는 "*"를 호출해야합니다. –

+0

이전 질문에 대한 답을 읽어주십시오.원하는 방식으로 연산자를 처리 할 임시 래퍼 (Point :: Scalar)를 반환 할 수 있음을 보여줍니다. –

관련 문제