在Ruby中,如何从正在扩展的模块应用attr_访问器?
我正试图通过将方法组织成单独的模块来模块化一些Ruby代码。最初我有这样的想法:在Ruby中,如何从正在扩展的模块应用attr_访问器?,ruby,Ruby,我正试图通过将方法组织成单独的模块来模块化一些Ruby代码。最初我有这样的想法: 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_
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
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
我试过这样做:
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
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
但是,不工作的部分是attr\u访问器
。我已经尝试了include
/extend
,def self.include(base)的所有不同组合;base.extend
,而我似乎找不到合适的组合来让所有东西协同工作。我该怎么做
更新:我想我遗漏的部分是,每个模块都可能同时具有实例方法和类方法。所以我现在有这样的东西:
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
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
类。以正确获得您想要的功能,您必须将extend
更改为include
,并在模块中提供included
块。这样,您就可以在一个模块中定义实例和类方法,只需包含该模块并适当地组织您的方法
可能需要对代码进行一点重新组织,但为了帮助解释更多内容,您可以
如果仍然不清楚,您可能需要查看。在模块中定义,因此只能在模块和类(即模块)上调用。它通过调用将给定模块中的常量、(实例)方法和(模块)变量添加到接收方
另一方面,在对象中定义,即不限于模块和类。它将给定模块中的实例方法添加到接收方,或者更准确地说,添加到接收方的单例类中
下面是一个带有实例方法的示例模块hello
:
module Mod
def hello
"Hello from #{self.class} '#{self}'"
end
end
如果我们扩展一个实例(与类相反),那么hello
将成为一个实例方法:
如果我们扩展一个类,那么hello
将成为一个类方法:
这是因为类方法实际上只是在类的单例类中定义的实例方法
也就是说,可以通过调用extend
和/或include
来定义类和实例方法:
1. <代码>扩展
和包括
这是最基本的一个,您可以将include Name
从Person移动到Joe
:
module Person
include Arms, Legs
end
class Joe
extend Person
include Name
end
2. <代码>扩展
和在超类中包含
或者,您可以将Person
创建为一个类,该类扩展s并包含s其他模块,并将其用作Joe
的超类:
class Person
extend Arms, Legs
include Name
end
class Joe < Person
end
4. <代码>从包含的中扩展
或者您可以从Joe
中包含Person
,并使用回调调用extend
:
module Person
include Name
def self.included(mod)
mod.extend Arms, Legs
end
end
class Joe
include Person
end
3和4从Joe
内部看起来很干净,但是包含或扩展Person
也定义了类或实例方法,这一点可能并不明显(甚至可能令人困惑)。如果我改为include
,那么类方法将变成实例方法。对不起,我误解了。谢谢,这无疑使事情更容易理解。我想我遗漏的部分仍然有问题,那就是Name
模块同时包含实例方法和类方法。我不认为attr\u accessor
是一种实例方法,但它只在使用include
时有效。因此,我只剩下尝试包含Name::InstanceMethods
和mod.extend Name::ClassMethods
了,但感觉很混乱。@Andrew您必须以某种方式扩展类方法和包含实例方法。也许有一种方法可以重组类/模块。