Ho una coppia di moduli che estendono metodo mancante:Come comporre moduli contenenti method_missing in rubino
module SaysHello
def respond_to?(method)
super.respond_to?(method) || !!(method.to_s =~ /^hello/)
end
def method_missing(method, *args, &block)
if (method.to_s =~ /^hello/)
puts "Hello, #{method}"
else
super.method_missing(method, *args, &block)
end
end
end
module SaysGoodbye
def respond_to?(method)
super.respond_to?(method) || !!(method.to_s =~ /^goodbye/)
end
def method_missing(method, *args, &block)
if (method.to_s =~ /^goodbye/)
puts "Goodbye, #{method}"
else
super.method_missing(method, *args, &block)
end
end
end
class ObjectA
include SaysHello
end
class ObjectB
include SaysGoodbye
end
Questo tutto funziona bene, per esempio ObjectA.new.hello_there
uscite "Hello, hello_there"
. Allo stesso modo, ObjectB.new.goodbye_xxx
uscite "Goodbye, xxx"
. respond_to?
funziona anche, ad es. ObjectA.new.respond_to? :hello_there
return true.
Tuttavia, questo non funziona molto bene quando si desidera utilizzare entrambi i SaysHello
e SaysGoodbye
:
class ObjectC
include SaysHello
include SaysGoodbye
end
Mentre ObjectC.new.goodbye_aaa
funziona correttamente, ObjectC.new.hello_a
agisce strano:
> ObjectC.new.hello_aaa
Hello, hello_aaa
NoMethodError: private method `method_missing' called for nil:NilClass
from test.rb:22:in `method_missing' (line 22 was the super.method_missing line in the SaysGoodbye module)
Produce correttamente, quindi genera un errore. Anche respond_to?
non è corretto, ObjectC.new.respond_to? :hello_a
restituisce false.
Infine, l'aggiunta di questa classe:
class ObjectD
include SaysHello
include SaysGoodbye
def respond_to?(method)
super.respond_to?(method) || !!(method.to_s =~ /^lol/)
end
def method_missing(method, *args, &block)
if (method.to_s =~ /^lol/)
puts "Haha, #{method}"
else
super.method_missing(method, *args, &block)
end
end
end
agisce anche in modo strano. ObjectD.new.lol_zzz
funziona, tuttavia ObjectD.new.hello_a and ObjectD.new.goodbye_t
rilascia entrambi un'eccezione di nome dopo aver emesso la stringa corretta. respond_to?
ha esito negativo anche per i metodi ciao e addio.
C'è un modo per far funzionare tutto correttamente? Una spiegazione di come method_missing
, Moduli e super
interagiscono sarebbe anche molto utile.
MODIFICA: coreyward ha risolto il problema, se uso super invece di super.<method-name>(args...)
in tutti i metodi che definisco, il programma funziona correttamente. Non capisco perché sia così, quindi ho fatto un'altra domanda al riguardo a What does super.<method-name> do in ruby?
moduli inclusi sono aggiunti alla catena di ereditarietà; non sostituiscono o sostituiscono i metodi. Quindi, se ogni metodo_missing chiama super, alla fine verranno tutti chiamati. Vedi la mia risposta qui sotto. – ChrisPhoenix