2014-02-20 46 views
1

我有一個模塊,並想混入一些方法作爲類方法和一些實例方法。如何在Ruby中的模塊中混入一些類方法和一些實例方法?

例如:

module Foo 
    def self.class_method 
    end 

    def instance_method 
    end 
end 

class Bar 
    include Foo 
end 

用法:

Bar.class_method 
Bar.new.instance_method 

是否有可能做到這一點的紅寶石?

如果沒有,是否可以定義哪些方法是類方法,哪些方法是Bar類中的實例方法?

要同時定義爲類和實例方法相同的方法。

回答

3

這種模式在Ruby中很常見。事實上,這很普通,ActiveSupport::Concern會將它抽象出來。

你典型的實現看起來是這樣的:

module Foo 
    def self.included(other_mod) 
    other_mod.extend ClassMethods 
    end 

    def instance_method 
    end 

    module ClassMethods 
    def class_method 
    end 
    end 
end 

class Bar 
    include Foo 
end 

你描述不以某種方式分裂包含模塊成多個部分不能輕易做到這一點,不過,很可惜。

+0

感謝關於將包含的模塊拆分爲多個部分的注意事項。我也在想這個。 –

3

你可以,但不是那樣。這是在一個模塊中包含實例和類方法的常見模式。

module Foo 
    def self.included(base) 
    base.extend ClassMethods 
    end 

    def instance_method 
    puts 'instance' 
    end 

    module ClassMethods 
    def class_method 
     puts 'class' 
    end 
    end 
end 

class Bar 
    include Foo 
end 

bar = Bar.new 
Bar.class_method #=> 'class' 
bar.instance_method #=> 'instance' 
1

你就近了。您可能注意到實例方法正常工作。類方法的問題在於它定義時爲self => Foo,所以它不響應Bar。如果您在self.class_method添加一行puts "I'm a module method",你會發現

Foo.class_method => "I'm a module method" 

下面就來完成你想要做什麼的簡單方法:

module Foo_class 
    attr_accessor :cat 
    def class_method 
    puts "I'm a class method" 
    end 
end 

module Foo_instance 
    def instance_method 
    puts "I'm an instance method" 
    end 
end 

class Bar 
    extend Foo_class 
    include Foo_instance 
end 

Bar.class_method  #=> I'm a class method 
Bar.cat = "meow" 
Bar.cat     #=> "meow" 
Bar.new.instance_method #=> I'm an instance method 

我添加了一個類的實例變量,@cat和訪問爲了它,只是爲了表明這是多麼容易。

Object#extend是偉大的,因爲你可以只添加實例變量和方法的模塊,就像你與Object#include到的mixin實例變量和方法做了,extend混合並將其作爲類的實例變量和類方法。你也可以這樣做:

bar = Bar.new 
bar.extend Foo_class 

有實例變量和方法Foo_class適用於實例bar

相關問題