How to overload operators with a method name in Ruby?
Let's say I have a class named Foo:
Class Foo
def method=(params)
puts params
end
def +(params)
puts params
end
def method+(params)
puts params
end
end
In the above, after initializing the class to a new object, which I'll call myobj (myobj = Foo.new), calling myobj.method = "string" and myobj + "strin开发者_Go百科g" will both print that string. However, a syntax error is thrown when I try to define method+. I want to be able to call myobj.method + "string". Can anyone help?
This is not actually a case of what characters can appear in method names ('+' is technically allowed), but rather the parsing and precedence rules of the language.
The reason def method=
works is that it is Ruby's special syntax for property accessors. When you define method=
, semantically you are saying that the foo has an accessible @method
instance variable, or at least acts like it.
It is a special case, and all other operators bind less strongly than the .
method call. In foo.method + "string"
, method
is called on foo
and then +("string")
is called on the result.
Ruby won't let you define a whatever+
method like it will with whatever=
- if you need the behaviour you're describing, you'll need to make a "method" object, define the +
operator for it, and return it from a call to Foo.method
:
class Method
def + (params)
puts params
end
def = (params)
puts params
end
end
class Foo
def + (params)
puts params
end
def method
return Method.new
end
end
I've moved the =
operator into the method object as well, but that one doesn't really matter (since you can def method=
) - it just seemed logical. And if you need to put this into practice, you should probably make Method a member class of Foo:
class Foo
class Method
end
end
so you keep your namespaces clean. You can always use Foo::Method
to get at that class when you need it.
Hope this helps!
A method is not an object, and operators are attributes of objects, not methods. This won't work.
精彩评论