Как составлять модули, содержащие method_missing в ruby ​​

У меня есть пара модулей, расширяющих метод, отсутствует:

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

Все это работает хорошо, например ObjectA.new. hello_there выводит «Hello, hello_there» . Аналогично, ObjectB.new.goodbye_xxx выводит «Goodbye, xxx» . response_to? ] также работает, например ObjectA.new.respond_to?: hello_there return true.

Однако это не очень хорошо работает, если вы хотите использовать оба SaysHello и ] SaysGoodbye :

class ObjectC
    include SaysHello
    include SaysGoodbye
end

Хотя ObjectC.new.goodbye_aaa работает правильно, ObjectC.new.hello_a ведет себя странно:

> 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)

Он выводит правильно, а затем выдает ошибку. Также response_to? неправильно, ObjectC.new.respond_to? : hello_a возвращает false.

Наконец, добавление этого класса:

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

Тоже странно. ObjectD.new.lol_zzz работает, однако ObjectD.new.hello_a и ObjectD.new.goodbye_t генерируют исключение имени после вывода правильной строки. response_to? также не работает для методов hello и goodbye.

Есть ли способ заставить все это работать правильно? Также было бы полезно объяснить, как взаимодействуют method_missing , Modules и super .

РЕДАКТИРОВАТЬ: Coreyward решил проблему, если я использую super вместо super. (args ...) во всех определяемых мной методах, программа работает правильно. Я не понимаю, почему это так, поэтому я задал еще один вопрос по этому поводу на Что super. делает в ruby?

9
задан Community 23 May 2017 в 12:17
поделиться