我试图通过将方法组织成单独的模块来模块化一些
Ruby代码.最初我有这样的事情:
@H_301_17@解决方法
class Joe attr_accessor :name def self.arms 2 end def self.legs 2 end end
我尝试过这样的事情:
class Joe extend Person end module Person include Name include Arms include Legs end module Name attr_accessor :name end module Arms def arms 2 end end module Legs def legs 2 end end
但是,无效的部分是attr_accessor.我尝试了include / extend,def self.included(base)的所有不同组合; base.extend我似乎无法找到合适的组合来使一切都协同工作.我怎样才能做到这一点?
更新:我认为我遗漏的部分是每个模块都可能有实例方法和类方法.所以我现在有这样的事情:
class Joe include Person end module Person include Name::InstanceMethods include Arms::InstanceMethods include Legs::InstanceMethods def self.included(base) base.extend Name::ClassMethods base.extend Arms::ClassMethods base.extend Legs::ClassMethods end end module Name module ClassMethods; end module InstanceMethods attr_accessor :name end end module Arms module ClassMethods def arms 2 end end module InstanceMethods; end end module Legs module ClassMethods def legs 2 end end module InstanceMethods; end end
虽然这有效,但感觉很麻烦.它也像Person模块对实例方法和类方法了解得太多.如果我要修改Name模块以删除空/未使用的ClassMethods模块,我还必须修改Person类.
include
在Module中定义,因此只能在模块和类(模块)上调用.它通过调用
append_features
将常量,(实例)方法和(模块)变量从给定模块添加到接收器.
另一方面,extend
在Object中定义,即它不限于模块和类.它将实例方法从给定模块添加到接收器,或者更确切地说,添加到接收器的单例类.
这是一个带有实例方法hello的示例模块:
module Mod def hello "Hello from #{self.class} '#{self}'" end end
如果我们扩展一个实例(而不是一个类),那么hello将成为一个实例方法:
str = 'abc' str.extend(Mod) str.hello #=> "Hello from String 'abc'"
如果我们扩展一个类,那么hello就成了一个类方法:
String.extend(Mod) String.hello #=> "Hello from Class 'String'"
也就是说,有几个选项可以通过调用extend和/或include来定义类和实例方法:
1.扩展和包括
这是最基本的一个,您可以将包括姓名从人员移动到Joe:
module Person include Arms,Legs end class Joe extend Person include Name end
2.扩展并包含在超类中
或者你可以使Person成为一个扩展并包含其他模块的类,并将其用作Joe的超类:
class Person extend Arms,Legs include Name end class Joe < Person end
接下来的选项涉及一些Ruby魔法 – 他们使用回调来调用包含在扩展上,反之亦然:
您可以使用extended
回调在Person中包含Name:
module Person include Arms,Legs def self.extended(mod) mod.include(Name) end end class Joe extend Person end
4.从内包延伸
或者您可以在Joe中包含Person并使用included
回调来调用extend:
module Person include Name def self.included(mod) mod.extend Arms,Legs end end class Joe include Person end
从Joe内部看来,3和4看起来很干净,但是包含或扩展Person也可能不明显(甚至可能令人困惑?)也定义了类或实例方法.