2016-10-16 8 views
7

я читал какой-то код, и я увидел что-то вдоль линийЧто + @ означает, как метод в рубин

module M 
    def [email protected] 
    self 
    end 
end 

Я был удивлен, что это правовой синтаксис, но когда я побежал ruby -c на файл (чтобы понять), он сказал, что это действительно. [email protected] также был именем юридического метода, когда я пробовал *@ или [email protected] оба из них были незаконными. Мне было интересно, что означает [email protected] и почему это законно?

ответ

12

рубин содержит несколько унарные операторы, в том числе +, -, !, ~, & и *. Как и в случае с другими операторами, вы также можете переопределить их. Для ~ и ! вы можете просто сказать def ~ и def !, поскольку у них нет двоичного аналога (например, вы не можете сказать a!b).

Однако для - и + там как унарный и бинарный вариант (например, a+b и +a являются действительным), так что если вы хотите, чтобы переопределить унарную версию вы должны использовать def [email protected] и def [email protected].

Также обратите внимание, что есть унарная версия * и &, но они имеют специальные значения. Для * он привязан к разбиению массива, и для & он привязан к преобразованию объекта в proc, поэтому, если вы хотите их использовать, вам необходимо переопределить to_a и to_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 –

1

Названия методов [email protected] и [email protected] используются перегружать унарные операторы + и - в Ruby (1.9+). Унарные операторы - это операторы, которые принимают только одно значение (например, value = -value).