我有一个模块,想把一些方法混合为类方法,一些方法作为实例方法。
例如:
module Foo
def self.class_method
end
def instance_method
end
end
class Bar
include Foo
end
用法:
Bar.class_method
Bar.new.instance_method
可以在Ruby中执行此操作吗?
如果没有,是否可以定义哪些方法是类方法,哪些是Bar类中的实例方法?
我 不 希望将同一方法定义为类和实例方法。
答案 0 :(得分: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
你不能轻易地完成这项工作,但不幸的是,不会以某种方式将包含的模块分成多个部分。
答案 1 :(得分: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'
答案 2 :(得分:1)
你很亲密。你可能注意到实例方法工作正常。类方法的问题是self => Foo
在定义时,因此它不响应Bar
。如果您在puts "I'm a module method"
中添加第self.class_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混合实例变量和方法一样,extend
混合它们在类实例变量和类方法中。你也可以这样做:
bar = Bar.new
bar.extend Foo_class
让Foo_class
中的实例变量和方法适用于实例bar
。