2013-08-12 23 views
5

Dostaję zaznajomieni z rubinem wysłać metody, ale z jakiegoś powodu, nie mogę zrobić coś takiegoPlus równa z rubinem wyślij wiadomość

a = 4 
a.send(:+=, 1) 

z jakiegoś powodu nie działa. Następnie próbowałem coś takiego, jak

a.send(:=, a.send(:+, 1)) 

Ale to też nie działa. Jaki jest właściwy sposób na ogień plus jest równy przez "wysłać"?

+4

Nie ma takiej metody '+ =', to po prostu skrót do 'a = a + 1', więc możesz napisać' a = a.send (: +, 1) 'jeśli musisz użyć metoda "wyślij". – taro

+1

Aby objaśnić, '+ =' jest obsługiwane na poziomie lexer i rozwijane do jego długiej formy. –

Odpowiedz

6

Myślę, że opcja jest tylko podstawowa:

a = a.send(:+, 1) 

To dlatego send jest dla komunikatów do obiektów. Przypisanie modyfikuje zmienną, a nie obiekt.


Jest możliwe, aby przypisać bezpośrednio do zmiennych o jakiejś meta-programowania, ale kod jest zawiłe, więc zdecydowanie najlepsze, co mogę znaleźć to:

a = 1 
var_name = :a 
eval "#{var_name} = #{var_name}.send(:+, 1)" 
puts a # 2 

lub używając instancji zmienne:

@a = 2 
var_name = :@a 
instance_variable_set(var_name, instance_variable_get(var_name).send(:+, 1)) 
puts @a # 3 
+1

Twój ostatni przykład może pominąć przypisanie 'var_name' i po prostu wykonaj to zamiast:' @ = 2; instance_variable_set (: @ a, instance_variable_get (: @ a) .send (: +, 1)); => 3' – d3vin

+1

@ d3ven: Tak, to było chwilę temu, ale myślę, że zachowałem tam 'var_name' dla łatwiejszego wizualnego porównania między dwoma podejściami. Możesz również "eval" a = a.send (: +, 1) "' w pierwszym przykładzie. . . więc 'var_name' po prostu wpisuje" możesz wybrać to dynamicznie "w każdym przypadku. –

0

To dlatego, że Ruby nie ma metody =. W Ruby = nie działają jak w C/C++, ale raczej przypisują nowe odwołanie do obiektu do zmiennej, a nie przypisują nowej wartości do zmiennej.

0

Patrz poniżej:

p 4.respond_to?(:"+=") # false 
p 4.respond_to?(:"=") # false 
p 4.respond_to?(:"+") # true 

a+=1 jest cukier syntaktyczny z a = a+1. Ale nie ma bezpośredniej metody. = to operator przypisania, a nie metoda. Z drugiej strony Object#send przyjmuje nazwę metody jako jej argument. W ten sposób twój kod nie będzie działał tak, jak tego szukasz.

+1

Powinieneś użyć ':" + = "' i ':" = "', aby uniknąć błędów składniowych. – Stefan

+0

@Stefan dzięki za nauczanie .. pomocne informacje .. :) –

0

Nie można wywołać metody na a, ponieważ a nie jest obiektem, jest zmienną, a zmienne nie są obiektami w Ruby. Wywołujesz metodę na 4, ale 4 nie jest tym, co chcesz zmodyfikować, . To po prostu niemożliwe.

Uwaga: możliwe jest zdefiniowanie metody o nazwie = lub += i wywołanie jej, ale oczywiście metody te będą istniały tylko dla obiektów, a nie dla zmiennych.

class Fixnum 
    define_method(:'+=') do |n| self + n end 
end 

a = 4 

a.send(:'+=', 1) 
# => 5 

a 
# => 4 
Powiązane problemy