W Rubim, jak sprawdzić, czy zdefiniowano metodę „foo = ()”?

81

W Rubim mogę zdefiniować metodę foo = (bar):

irb(main):001:0> def foo=(bar)
irb(main):002:1>   p "foo=#{bar}"
irb(main):003:1> end
=> nil

Teraz chciałbym sprawdzić, czy został zdefiniowany,

irb(main):004:0> defined?(foo=)
SyntaxError: compile error
(irb):4: syntax error, unexpected ')'
 from (irb):4
 from :0

Jaka jest właściwa składnia do użycia w tym miejscu? Zakładam, że musi istnieć sposób na uniknięcie „foo =”, tak aby zostało przetworzone i przekazane poprawnie do zdefiniowanego? operator.

Alex Boisvert
źródło

Odpowiedzi:

132

Problem polega na tym, że foo=metoda jest przeznaczona do stosowania w zadaniach. Możesz użyć defined?w następujący sposób, aby zobaczyć, co się dzieje:

defined? self.foo=()
#=> nil
defined? self.foo = "bar"
#=> nil

def foo=(bar)
end

defined? self.foo=()
#=> "assignment"
defined? self.foo = "bar"
#=> "assignment"

Porównaj to z:

def foo
end

defined? foo
#=> "method"

Aby sprawdzić, czy foo=metoda jest zdefiniowana, należy respond_to?zamiast tego użyć :

respond_to? :foo=
#=> false

def foo=(bar)
end

respond_to? :foo=
#=> true
molf
źródło
Dzięki! To rozwiązuje mój problem. Nadal jestem ciekawy, czy istnieje sposób na uniknięcie foo = tak, że można go nakarmić zgodnie z definicją? ale przynajmniej teraz mogę przejść dalej.
Alex Boisvert
1
Problem polega na tym, że foo=jest on zawsze używany w zadaniach, więc Ruby zwróci, "assignment"jeśli przetestujesz defined? foo()(zobacz zaktualizowaną odpowiedź).
molf
43

Możesz sprawdzić, czy metoda istnieje, używając respond_to?metody i przekazać jej symbol, np. bar.respond_to?(:foo=)Aby zobaczyć, czy obiekt barma metodę foo=. Jeśli chcesz wiedzieć, czy instancje klasy odpowiadają na metodę, której możesz użyć method_defined?na klasie (lub module), np Foo.method_defined?(:bar=).

defined?nie jest metodą, ale operatorem, który zwraca opis operandu (lub nil, jeśli nie jest zdefiniowany, dlatego można go użyć w instrukcji if). Operandem może być dowolne wyrażenie, tj. Stała, zmienna, przypisanie, metoda, wywołanie metody itp. Powodem, dla którego to nie działa, kiedy to robisz, defined?(foo=)są nawiasy, pomiń je i powinno działać bardziej lub mniej zgodnie z oczekiwaniami. To powiedziawszy, defined?jest dość dziwnym operatorem i nikt nie używa go do testowania istnienia metod.

Theo
źródło
To jest respond_to ?, a nie responds_to?
0x4a6f4672
3
Ach, pisownia podstawowej biblioteki Ruby ... respond_to?, start_with?, end_with?.
Theo
3
stackoverflow.com/questions/5280556/… ma ładne wyjaśnienie wyboru stojącego za nazewnictwem TL; DRyou.knock if you.respond_to?(:knock)
drewish