【问题标题】:ruby mixin with class methods, instance methods, and class variablesruby mixin 与类方法、实例方法和类变量
【发布时间】:2011-06-23 19:29:29
【问题描述】:

您知道如何定义@@method_names 类变量,以便my_macroinvoke_methods 可以按预期使用它吗?谢谢!

module MyModule

    module ClassMethods    
        def my_macro method_name, options = { }
            define_method method_name do
                puts "defining #{method_name} with #{options}"
            end
            @@method_names << method_name
        end    
    end

    def invoke_methods
        @@method_names.each { |method_name| send method_name }
    end

    def self.included includer
        includer.extend ClassMethods
    end

end

class MyClass
    include MyModule
    my_macro :method_foo, :bar => 5
    my_macro :method_baz, :wee => [3,4]
end

MyClass.new.invoke_methods

【问题讨论】:

  • 也许在@@method_names &lt;&lt; method_name之前先初始化@@method_names = []
  • 我试过这个:@@method_names = [] unless @@method_names; @@method_names &lt;&lt; method_name 但得到了NameError: uninitialized class variable @@method_names in MyModule::ClassMethods
  • 这样做而不是使用除非:@@method_names = @@method_names || []
  • 谢谢。当然,更红,但仍然给出同样的错误。

标签: ruby mixins


【解决方案1】:

这是一个工作版本。更改注释:

module MyModule
    module ClassMethods
        @@method_names ||= [] #move this up here
        def my_macro method_name, options = { }
            define_method method_name do
                puts "defining #{method_name} with #{options}"
            end
            @@method_names << method_name
        end

        #added this (rename as required)
        def the_methods
          @@method_names
        end
    end

    def invoke_methods
        #changed this call
        self.class.the_methods.each { |method_name| send method_name }
    end

    def self.included includer
        includer.extend ClassMethods
    end
end

class MyClass
    include MyModule
    my_macro :method_foo, :bar => 5
    my_macro :method_baz, :wee => [3,4]
end

MyClass.new.invoke_methods

【讨论】:

    【解决方案2】:
    module MyModule
    
        module ClassMethods    
            def my_macro method_name, options = { }
                define_method method_name do
                    puts "defining #{method_name} with #{options}"
                end
                @method_names ||= []
                @method_names << method_name
            end  
    
            def method_names
              @method_names
            end  
        end
    
        def invoke_methods
            self.class.method_names.each { |method_name| send method_name }
        end
    
        def self.included includer
            includer.extend ClassMethods
        end
    
    end
    
    class MyClass
        include MyModule
        my_macro :method_foo, :bar => 5
        my_macro :method_baz, :wee => [3,4]
    end
    
    MyClass.new.invoke_methods
    

    【讨论】:

    • 如何让它使用类变量而不是实例变量?
    • 我认为不可能从类方法访问类变量。类方法中的@@var 是一件很奇怪的事情,不要这样做。一般来说,即使在“正常”情况下,也不建议使用类变量。
    • 可以从类方法访问类变量 - 不确定您的意思是什么(class A; @@m = "hello"; def self.x; p @@m; end; end; A.x; )。但我同意你的其余陈述。
    • @Zabba 原来“类”变量是在实例方法中定义的@@v,并且这样的变量在同一个类的实例之间共享(并且也是继承的!):class A; def a; @@a = 1 end; def b; puts @@a end; end; A.new.a; A.new.b。 @@v 在类上下文中定义是完全不同的野兽。为什么需要它?
    猜你喜欢
    • 2013-05-28
    • 1970-01-01
    • 1970-01-01
    • 2011-08-27
    • 2014-03-06
    • 1970-01-01
    • 2021-06-03
    • 2017-02-15
    • 1970-01-01
    相关资源
    最近更新 更多