What does +@ mean as a method in ruby

后端 未结 2 1889
余生分开走
余生分开走 2020-12-16 02:28

I was reading some code and I saw something along the lines of

module M
  def +@
    self
  end
end

I was surprised that this was legal sy

相关标签:
2条回答
  • 2020-12-16 03:01

    Ruby contains a few unary operators, including +, -, !, ~, & and *. As with other operators you can also redefine these. For ~ and ! you can simply just say def ~ and def ! as they don't have a binary counterpart (e.g. you cannot say a!b).

    However for - and + there is both a unary, and a binary version (e.g. a+b and +a are both valid), so if you want to redefine the unary version you have to use def +@ and def -@.

    Also note that there is a unary version of * and & as well, but they have special meanings. For * it is tied to splatting the array, and for & it is tied to converting the object to a proc, so if you want to use them you have to redefine to_a and to_proc respectively.

    Here is a more complete example showing all kinds of the unary operators:

    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 :("]
    

    In your example the Module just simply defines an unary + operator, with a default value of not doing anything with the object (which is a common behaviour for the unary plus, 5 and +5 usually mean the same thing). Mixing in with any class would mean the class immediately gets support for using the unary plus operator, which would do nothing much.

    For example (using 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"
    

    Note that in this example you can clearly see from the error message that the +@ method is missing from the class

    Note that the above example will be different from Ruby 2.3, as the unary minus and plus are defined for Strings since that version, and they refer to returning a frozen and unfrozen string from the original.

    0 讨论(0)
  • 2020-12-16 03:09

    The method names +@ and -@ are used to overload the unary operators + and - in Ruby (1.9+). Unary operators are operators which only take a single value (e.g. value = -value).

    0 讨论(0)
提交回复
热议问题