gpt4 book ai didi

ruby - 在 Ruby 中,如何从正在扩展的模块中应用 attr_accessor?

转载 作者:数据小太阳 更新时间:2023-10-29 06:58:24 26 4
gpt4 key购买 nike

我正在尝试通过将方法组织到单独的模块中来模块化一些 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_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 类。

最佳答案

includeModule 中定义,因此只能在模块和类(它们是模块)上调用。它通过调用 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。 扩展包含

这是最基本的,您可以将 include Name 从 Person 移动到 Joe:

module Person
include Arms, Legs
end

class Joe
extend Person
include Name
end

2。 extendinclude in superclass

或者你可以让 Person 成为一个 extendinclude 其他模块的类,并将它用作 Joe的父类(super class):

class Person
extend Arms, Legs
include Name
end

class Joe < Person
end

下一个选项涉及一些 Ruby 魔法 - 它们使用回调在 extend 上调用 include,反之亦然:

3。 include 来自 extended

您可以使用 extendedPerson 中回调到 include Name:

module Person
include Arms, Legs
def self.extended(mod)
mod.include(Name)
end
end

class Joe
extend Person
end

4。 extendincluded

或者您可以从 Joe包含 Person 并使用 included调用 extend 的回调:

module Person
include Name
def self.included(mod)
mod.extend Arms, Legs
end
end

class Joe
include Person
end

3 和 4 在 Joe 中看起来很干净,但包含或扩展 Person 也定义了类或实例方法可能并不明显(甚至可能令人困惑?)。

关于ruby - 在 Ruby 中,如何从正在扩展的模块中应用 attr_accessor?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32901178/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com