【问题标题】:Callback for classes defined inside a Module模块内定义的类的回调
【发布时间】:2010-11-16 04:24:05
【问题描述】:

Ruby 已经有几个built-in callbacks。这种情况有回调吗?有点像 method_added,但用于模块内的类(或常量),而不是类内的实例方法。

【问题讨论】:

    标签: ruby metaprogramming


    【解决方案1】:

    据我所知,与您所描述的完全不一样。但是,您可以使用Class::inherited 创建自己的方法。

    module MyModule
      def self.class_added(klass)
        # ... handle it
      end
      class ::Class
        alias_method :old_inherited, :inherited
        def inherited(subclass)
          MyModule.class_added(subclass) if /^MyModule::\w+/.match subclass.name
          old_inherited(subclass)
        end
      end
    end
    
    module MyModule
      # now add classes
    end
    

    【讨论】:

    • 是的,将方法修补到 Class 有其自身的问题。特别是,在任何定义了自己的回调并且不调用 super 的类上都不会调用inherited。另一种方法是使用 parsetree 更改语法树(尽管目前在所有情况下都没有 1.9)。但似乎缺少回调。我问是因为 Gregor 的帖子很旧,而且文档没有提到这个功能。
    【解决方案2】:

    您可以通过定义自己的def_class 方法来尝试这种方法:

    module M
      def self.const_missing(name)
        const_set(name, Class.new)
      end
    
      def self.def_class(klass, &block)
        class_added(klass.name)
        klass.class_eval(&block)
      end
    end
    
    module M
      def self.class_added(klass)
        puts "new class added: #{klass}"
      end
    
      def_class Hello do
        def hello
          puts "hello!"
        end
      end
    end
    
    h = M::Hello.new.hello #=> "hello!"
    

    【讨论】:

    • 这是一个很好的技巧。使用 parse tree hack,甚至可以在不需要用户更改自己的模块的情况下这样做。但是解析树黑客将引入另一个范围。或者引入另一种自定义的类似模块的方法。不完美。我知道 Matz 不想添加更多回调,但确实缺少一些。
    猜你喜欢
    • 1970-01-01
    • 2012-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-27
    • 1970-01-01
    • 1970-01-01
    • 2019-05-26
    相关资源
    最近更新 更多