Ruby 包含一些一元运算符,包括 +、-、!、~、& 和 *。与其他运算符一样,您也可以重新定义这些运算符。对于~ 和!,您可以简单地说def ~ 和def !,因为它们没有二进制对应项(例如,您不能说a!b)。
但是,- 和 + 既有一元版本,也有二进制版本(例如,a+b 和 +a 都是有效的),所以如果你想重新定义一元版本,你必须使用 @ 987654336@和def -@。
另请注意,* 和 & 也有一个一元版本,但它们具有特殊含义。对于*,它与喷溅数组相关联,对于&,它与将对象转换为proc相关,因此如果要使用它们,则必须分别重新定义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 通常意味着相同的事情)。与任何类混合意味着该类会立即获得对使用一元加号运算符的支持,这无济于事。
例如(使用 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"
请注意,在本例中,您可以从错误消息中清楚地看到类中缺少 +@ 方法
请注意,上面的示例将与 Ruby 2.3 不同,因为自该版本以来为字符串定义了一元减号和加号,它们指的是从原始字符串返回一个冻结和未冻结的字符串。