2016-10-16 64 views

回答

12

红宝石包含了一些一元运算符,包括+-!~&*。与其他运营商一样,您也可以重新定义这些。对于~!,您可以简单地说def ~def !,因为它们没有二进制对应部分(例如,您不能说a!b)。

然而,对于-+有两个一元和二进制版本(例如a+b+a都是有效的),所以如果你想重新定义,你必须使用def [email protected]def [email protected]一元版本。

另请注意,还有一个*&的一元版本,但它们有特殊的含义。对于*而言,它与splatting数组有关,并且对于&它将对象转换为proc,所以如果要使用它们,则必须分别重新定义to_ato_proc

这里是在各种一元运算符的一个更完整的例子:

class SmileyString < String 
    def [email protected] 
    SmileyString.new(self + " :)") 
    end 

    def [email protected] 
    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通常意味着同样的事情)。与任何类混合意味着该类会立即得到使用一元加运算符的支持,而该运算符不会做任何事情。

例如(使用红宝石<=2.2):

module M 
    def [email protected] 
    self 
    end 
end 

p +"Hello"  # => NoMethodError: undefined method `[email protected]' for "Hello":String 

class String 
    include M 
end 

p +"Hello"  # => "Hello" 

注意,在本实施例中可以清楚地从该[email protected]方法是从类缺少

注意,上述示例中的错误消息见将与Ruby 2.3不同,因为从该版本开始,为字符串定义了一元减号和加号,它们指的是从原始数据返回冻结和解冻的字符串。

+0

体面的解释,+1 –