Ruby 模块包含的钩子而不是常规扩展?
Ruby Module's included hook instead of regular extending?
有一种通用方法可以通过其包含的钩子从模块中添加 class 方法,然后使用 ClassMethods 子模块扩展基础 class。这种方式在书 "Metaprogramming Ruby 2: Program Like the Ruby Pros" 中有描述。这是那里的一个例子:
module CheckedAttributes
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def attr_checked(attribute, &validation)
define_method "#{attribute}=" do |value|
raise 'Invalid attribute' unless validation.call(value)
instance_variable_set("@#{attribute}", value)
end
define_method attribute do
instance_variable_get "@#{attribute}"
end
end
end
end
class Person
include CheckedAttributes
attr_checked :age do |v|
v >= 18
end
end
但是首先包含几乎是空的模块,然后再用一个模块扩展它的包含器的原因是什么?为什么不直接用目标模块本身扩展 class?
module CheckedAttributes
def attr_checked(attribute, &validation)
define_method "#{attribute}=" do |value|
raise 'Invalid attribute' unless validation.call(value)
instance_variable_set("@#{attribute}", value)
end
define_method attribute do
instance_variable_get "@#{attribute}"
end
end
end
class Person
extend CheckedAttributes
attr_checked :age do |v|
v >= 18
end
end
上面的代码是否完全等同于本书中的初始示例?或者有什么陷阱?
我不知道你从哪里得到这段代码,但这种涉及 ClassMethods
的模式通常用于你想要改变 both [=20] 的情况=] 和 eigenclass 以避免同时调用 include Foo
和 extend Bar
。
module Named
def self.included(base)
base.extend ClassMethods
end
def describe
"Person is: #{name}"
end
module ClassMethods
def name!
define_method "name=" do |value|
raise 'Invalid attribute' unless validation.call(value)
instance_variable_set("@name", value)
end
define_method "name" do
instance_variable_get "@name"
end
end
end
end
class Person
include Named
name!
end
p = Person.new
p.name = "Trump"
p.describe #⇒ "Person is: Trump"
在您的示例中,它没有任何意义。
有一种通用方法可以通过其包含的钩子从模块中添加 class 方法,然后使用 ClassMethods 子模块扩展基础 class。这种方式在书 "Metaprogramming Ruby 2: Program Like the Ruby Pros" 中有描述。这是那里的一个例子:
module CheckedAttributes
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def attr_checked(attribute, &validation)
define_method "#{attribute}=" do |value|
raise 'Invalid attribute' unless validation.call(value)
instance_variable_set("@#{attribute}", value)
end
define_method attribute do
instance_variable_get "@#{attribute}"
end
end
end
end
class Person
include CheckedAttributes
attr_checked :age do |v|
v >= 18
end
end
但是首先包含几乎是空的模块,然后再用一个模块扩展它的包含器的原因是什么?为什么不直接用目标模块本身扩展 class?
module CheckedAttributes
def attr_checked(attribute, &validation)
define_method "#{attribute}=" do |value|
raise 'Invalid attribute' unless validation.call(value)
instance_variable_set("@#{attribute}", value)
end
define_method attribute do
instance_variable_get "@#{attribute}"
end
end
end
class Person
extend CheckedAttributes
attr_checked :age do |v|
v >= 18
end
end
上面的代码是否完全等同于本书中的初始示例?或者有什么陷阱?
我不知道你从哪里得到这段代码,但这种涉及 ClassMethods
的模式通常用于你想要改变 both [=20] 的情况=] 和 eigenclass 以避免同时调用 include Foo
和 extend Bar
。
module Named
def self.included(base)
base.extend ClassMethods
end
def describe
"Person is: #{name}"
end
module ClassMethods
def name!
define_method "name=" do |value|
raise 'Invalid attribute' unless validation.call(value)
instance_variable_set("@name", value)
end
define_method "name" do
instance_variable_get "@name"
end
end
end
end
class Person
include Named
name!
end
p = Person.new
p.name = "Trump"
p.describe #⇒ "Person is: Trump"
在您的示例中,它没有任何意义。