我正在阅读一些代码,我看到了
的内容module M
def +@
self
end
end
我很惊讶这是合法的语法,但是当我在文件上运行ruby -c
(对于lint)时,它说它是有效的。 -@
也是一个合法的方法名称,但当我尝试*@
或d@
时,这两个都是非法的。我想知道+@
意味着什么,为什么合法?
答案 0 :(得分:16)
Ruby包含一些一元运算符,包括+
,-
,!
,~
,&
和*
。与其他运营商一样,您也可以重新定义这些运营商。对于~
和!
,您只需说出def ~
和def !
因为他们没有二元对应物(例如,您不能说a!b
)
但是对于-
和+
,有一元和二元版本(例如a+b
和+a
都有效),所以如果要重新定义您必须使用def +@
和def -@
的一元版本。
另请注意,*
和&
的一元版本也有,但它们具有特殊含义。对于*
,它与splatting数组相关联,对于&
,它与将对象转换为proc绑定在一起,因此如果要使用它们,则必须重新定义to_a
和{分别为{1}}。
这是一个更完整的示例,显示了所有类型的一元运算符:
to_proc
在你的例子中,模块只是简单地定义一个一元+运算符,默认值是不对对象做任何事情(这是一元加号的常见行为,class SmileyString < String
def +@
SmileyString.new(self + " :)")
end
def -@
SmileyString.new(self + " :(")
end
def ~
SmileyString.new(self + " :~")
end
def !
SmileyString.new(self + " :!")
end
def to_proc
Proc.new { |a| SmileyString.new(self + " " + a) }
end
def to_a
[SmileyString.new(":("), self]
end
end
a = SmileyString.new("Hello")
p +a # => "Hello :)"
p ~a # => "Hello :~"
p *a # => [":(", "Hello"]
p !a # => "Hello :!"
p +~a # => "Hello :~ :)"
p *+!-~a # => [":(", "Hello :~ :( :! :)"]
p %w{:) :(}.map &a # => ["Hello :)", "Hello :("]
和5
通常意思是一样的)。混入任何一个类都意味着该类立即获得使用一元加运算符的支持,这将不会做任何事情。
例如(使用ruby +5
):
<=2.2
请注意,在此示例中,您可以从错误消息中清楚地看到类中缺少module M
def +@
self
end
end
p +"Hello" # => NoMethodError: undefined method `+@' for "Hello":String
class String
include M
end
p +"Hello" # => "Hello"
方法
请注意,上面的示例与Ruby 2.3不同,因为从该版本开始为字符串定义了一元减号和加号,它们指的是从原始字符串返回冻结和解冻的字符串。
答案 1 :(得分:1)
方法名称+@
和-@
用于重载Ruby(1.9+)中的一元运算符+
和-
。
一元运算符是仅采用单个值的运算符(例如value = -value
)。