+@ 作为 ruby 中的方法是什么意思
What does +@ mean as a method in ruby
我正在阅读一些代码,我看到了一些类似
的内容
module M
def +@
self
end
end
我很惊讶这是合法的语法,但是当我 运行 ruby -c
在文件上(对 lint)它说它是有效的。 -@
也是一个合法的方法名称,但当我尝试 *@
或 d@
时,这两个都是非法的。我想知道 +@
是什么意思,为什么合法?
方法名+@
和-@
用于重载Ruby(1.9+)中的一元运算符+
和-
。
一元运算符是只接受单个值的运算符(例如 value = -value
)。
Ruby 包含一些一元运算符,包括 +
、-
、!
、~
、&
和 *
.与其他运算符一样,您也可以重新定义它们。对于 ~
和 !
你可以简单地说 def ~
和 def !
因为它们没有二进制对应物(例如你不能说 a!b
)。
但是 -
和 +
都有一元和二进制版本(例如 a+b
和 +a
都是有效的),所以如果你想要重新定义一元版本,您必须使用 def +@
和 def -@
.
另请注意,*
和 &
也有一个一元版本,但它们具有特殊含义。对于 *
来说,它与展开数组有关,而对于 &
来说,它与将对象转换为过程有关,所以如果你想使用它们,你必须重新定义 to_a
和 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
和 +5
通常表示同一件事)。与任何 class 混合将意味着 class 立即获得对使用一元加运算符的支持,这不会做太多事情。
例如(使用ruby <=2.2
):
module M
def +@
self
end
end
p +"Hello" # => NoMethodError: undefined method `+@' for "Hello":String
class String
include M
end
p +"Hello" # => "Hello"
注意,在这个例子中你可以从错误信息中清楚地看到class
缺少+@
方法
请注意,上面的示例将与 Ruby 2.3 不同,因为从该版本开始,为字符串定义了一元减号和加号,它们指的是从原始字符串返回冻结和解冻的字符串。
我正在阅读一些代码,我看到了一些类似
的内容module M
def +@
self
end
end
我很惊讶这是合法的语法,但是当我 运行 ruby -c
在文件上(对 lint)它说它是有效的。 -@
也是一个合法的方法名称,但当我尝试 *@
或 d@
时,这两个都是非法的。我想知道 +@
是什么意思,为什么合法?
方法名+@
和-@
用于重载Ruby(1.9+)中的一元运算符+
和-
。
一元运算符是只接受单个值的运算符(例如 value = -value
)。
Ruby 包含一些一元运算符,包括 +
、-
、!
、~
、&
和 *
.与其他运算符一样,您也可以重新定义它们。对于 ~
和 !
你可以简单地说 def ~
和 def !
因为它们没有二进制对应物(例如你不能说 a!b
)。
但是 -
和 +
都有一元和二进制版本(例如 a+b
和 +a
都是有效的),所以如果你想要重新定义一元版本,您必须使用 def +@
和 def -@
.
另请注意,*
和 &
也有一个一元版本,但它们具有特殊含义。对于 *
来说,它与展开数组有关,而对于 &
来说,它与将对象转换为过程有关,所以如果你想使用它们,你必须重新定义 to_a
和 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
和 +5
通常表示同一件事)。与任何 class 混合将意味着 class 立即获得对使用一元加运算符的支持,这不会做太多事情。
例如(使用ruby <=2.2
):
module M
def +@
self
end
end
p +"Hello" # => NoMethodError: undefined method `+@' for "Hello":String
class String
include M
end
p +"Hello" # => "Hello"
注意,在这个例子中你可以从错误信息中清楚地看到class
缺少+@
方法
请注意,上面的示例将与 Ruby 2.3 不同,因为从该版本开始,为字符串定义了一元减号和加号,它们指的是从原始字符串返回冻结和解冻的字符串。