2011-09-01 154 views
2

这间共享的方法是我的尝试:如何红宝石模块

module A 
    def self.method1; "method1"; end 
    def method2; "method2"; end 
end 

module B; include A; end 

B.method1 # => error 
B.method2 # => error 
B::method1 # => error 
B::method2 # => error 

我想避免复制和粘贴两个模块之间的等效代码。我在这里使用模块而不是类的原因是因为我不需要每个模块的多个实例,因为它们只是保存常量(此时为其他模块)。

解决此问题的最佳方法是什么?

+0

如果您只想要此代码的一个实例,为什么不使用单例? –

+0

主要是因为我不知道该解决方案的优缺点。有些人甚至说他们是邪恶的,而另一些人似乎认为他们是好的。你怎么看? – benekastah

+0

正确使用它们可能会有所帮助,但我不确定您的使用情况,所以我无法确定。 –

回答

6

普通include只给你实例方法(method2在你的特定代码段)。如果你想分享模块级的方法 - 提取它们与它独立的模块和其他extend模块:

module A 
    extend self  # to be able to use A.method1 

    def method1 
    "method1" 
    end 
end 

module B 
    extend A 
end 

B.method1  # => "method1" 

它也是include可能获取模块级的方法,但有一点扭曲,用钩子方法:

module A 
    def self.included(other) 
    other.extend ModuleMethods # this is where the magic happens 
    end 

    def instance_method 
    'instance method' 
    end 

    module ModuleMethods 
    def module_method 
     'module method' 
    end 
    end 

    extend ModuleMethods  # to be able to use A.module_method 
end 


module B 
    include A 
end 

B.module_method  #=> "module method" 
B.instance_methods  #=> [:instance_method] 
+0

请注意,这不会给你A.method1 - 如果你想这样做,一个选项将是在A. –

+0

@Greg内调用“扩展自我”这是正确的,好点。 –

1

首先,请注意A.method2也不起作用。您可以创建对象,包括A(或B),将有method2

class C 
    include B # (or A) 
end 
c = C.new 
c.method2 

因此,对于method2它只是工作,你打算。

关于method1,它是对象A的单例方法,无法继承它。