我的应用程序中有一个单例,可以跨应用程序重用。我希望该单例从我的类中获取一些默认方法,但也能够自定义模块/本征类。最重要的是,我不想在每次调用实用程序单例时调用instance
。
这是一个例子。我们说我的默认类是Universe::Earth
。然后我想在我的应用程序中使用Earth
模块"扩展"那个班。
module Universe
class Earth
def self.grow!
@grown = true
end
end
end
module Earth
class < Universe::Earth << self; end
grow!
end
当它运行时,grow!
是NoMethodError
。
试过这些方法:
Class.new(Goodluck::Contest) << self
class < Universe::Earth << self; end
extend Universe::Earth
如何让它发挥作用?
答案 0 :(得分:0)
这是你要找的东西吗?
module Universe
class Earth
def self.grow!
@grown = true
end
end
end
module Earth
Universe::Earth.class_eval do
define_method(:instance_howdy) do
puts "instance_howdy!"
end
end
def (Universe::Earth).class_howdy
puts "class_howdy!"
end
end
Universe::Earth.methods(false) #=> [:grow!, :class_howdy]
Universe::Earth.instance_methods(false) #=> [:instance_howdy]
Universe::Earth.new.instance_howdy #=> instance_howdy!
Universe::Earth.class_howdy #=> class_howdy!
[编辑:如果您只想设置@grown => true
并检索其值,则只需:
module Earth
Universe::Earth.grow! #=> true
end
验证
Universe::Earth.instance_variable_get("@grown") #=> true
如果您还想为类实例变量添加一个访问器,您可以这样做:
def add_class_accessor(c, accessor, var)
c.singleton_class.class_eval("#{accessor} :#{var}")
end
Universe::Earth.methods(false)
#=> [:grow!]
module Earth
Universe::Earth.grow! #=> true
add_class_accessor(Universe::Earth, "attr_accessor", "grown")
end
Universe::Earth.methods(false)
#=> [:grow!, :grown, :grown=]
Universe::Earth.grown
#=> true
Universe::Earth.grown = "cat"
#=> "cat"
Universe::Earth.grown
#=> "cat"
Ruby 1.9.2中添加了Object#singleton_class。对于早期版本,您可以这样做:
def add_class_accessor(c, accessor, var)
eigenclass = class << c; self; end
eigenclass.class_eval("#{accessor} :#{var}")
end
您可以考虑将add_class_accessor
放入要包含的模块中。您可能添加到同一模块的其他方法可能是:
add_instance_method(klass, method, &block)
add_class_method(klass, method, &block)
add_instance_accessor(klass, accessor, var)
<强>:潮强>