Ruby on rails 自我包含–;在Ruby中包含模块中的类方法
我读了这篇文章:–但仍然不知道什么时候你会使用Ruby on rails 自我包含–;在Ruby中包含模块中的类方法,ruby-on-rails,ruby,Ruby On Rails,Ruby,我读了这篇文章:–但仍然不知道什么时候你会使用self.included do。。。结束模块中的块 这篇文章说,当你包含模块时,块中的代码将被运行,但是如果模块的唯一目的是被包含,那又有什么意义呢?那代码不需要运行吗?为了让代码运行,那个块不需要存在,对吗 以下两者之间的区别是什么: module M def self.included(base) base.extend ClassMethods base.class_eval do scope :disable
self.included do。。。结束模块中的
块
这篇文章说,当你包含模块时,块中的代码将被运行,但是如果模块的唯一目的是被包含,那又有什么意义呢?那代码不需要运行吗?为了让代码运行,那个块不需要存在,对吗
以下两者之间的区别是什么:
module M
def self.included(base)
base.extend ClassMethods
base.class_eval do
scope :disabled, -> { where(disabled: true) }
end
end
module ClassMethods
...
end
end
vs
我试图修改上面的模块
,以帮助您理解模块(关注点)如何有助于代码重用
self.included
是一个钩子,当类中包含模块时,它会自动运行
模块ClassMethods
中声明的任何方法都将成为包含此模块的类的类方法
模块ClassMethods
之外声明的任何方法都将成为包含此模块的类的实例方法
例如,假设有一个类产品,并且您已经将模块包含在其中
class Product < ActiveRecord::Base
include M
puts 'after including M'
end
它还提供了可重用性,将这个模块M包含在任何类中,该类可以访问模块中描述的所有方法
而您的第二个示例仅仅是基本模块的示例
module N
def self.abc
puts 'basic module'
end
end
现在,只能使用此模块访问模块中定义的方法
N.abc#输出“基本模块”
class Product < ActiveRecord::Base
include N
end
类产品
Product.abc#引发异常,在类Product上找不到方法
Product.new.abc#引发异常,在类Product的对象上找不到方法
我希望这能帮助你更好地理解模块的概念。
如果您还有任何疑问,请告诉我。这两个例子有什么不同?
第一个代码块将ClassMethods
中的类方法添加到include类中,并对其调用scope
方法。第二个函数既不做这两件事,也会导致一个NoMethodError
,因为模块没有scope
类方法<代码>自身。包含模块后,包含类上的某些类方法将不可用
有关模块包含在Ruby中如何工作的完整故事,请阅读我的回答:如果一个模块的唯一目的是被包括在内,
self.include
有什么意义?
包含不是模块的唯一目的。它们还可用于其他用途,如名称空间或存储各种类方法,然后可在模块本身上调用这些类方法
为什么Ruby不自动包含类方法?
从理论上讲,Ruby可以自动将模块中定义的所有类方法添加到include类中,但实际上这是一个坏主意,因为将无法再选择是否要包含类方法-每次都会包含所有类方法,是否打算将其包括在内。考虑这个例子:
module M
def self.class_method
"foo"
end
def self.configure_module
# add configuration for this module
end
end
class C
include M
end
这里,显然不应将configure_module
方法添加到C
,因为其目的是为模块对象设置配置。然而,如果我们有类方法的自动包含,您将无法阻止它被包含
但所有实例方法都已包含在内!那怎么样?
模块中的实例方法只有包含在类中时才真正有用,因为模块不能有实例,只有类才能有实例。因此,在一个模块中,每个实例方法都应该包含在工作的某个地方
模块上的“类”方法是不同的,因为它可以在模块本身上调用,所以无论是否也添加到include类中,它都可以很好地使用。这就是为什么你最好在这里选择。听起来像是包含块将这些变量从另一个模块带到另一个模块。如果没有它,它不会工作吗?试着运行一个带有一些值的示例,看看它是否工作,请让我知道。你改变了密码?!!!为什么Product.abc即使包含了一个例外?是因为
#abc
仍然只在模块N的范围内,所以产品不能调用它吗?所以类方法必须在包含的和基.extend
块内,而实例方法只能正常定义吗?是的abc
仍然只能通过模块访问。当我们包含一个模块时,该模块中的类方法就不会包含在类中。这些方法仅适用于模块。@stackjlei-您甚至可以在self.included范围内定义实例方法。正如我告诉您的,self.include会在类中包含模块时立即调用,它可以用于为类定义范围
,或者在包含模块时要执行某些操作<代码>模块类方法
也用于声明类方法。如果仍然存在疑问,请随时询问left@stackjlei我刚刚添加了一个答案,详细解释了幕后发生了什么,以及为什么我们首先要使用self.include
块。你能用include解释一下原因吗“仅使其实例方法可用”?如果它们也使类方法可用,不是更容易吗?这样做有什么错吗?是因为包含只会在ancestorial查找中添加实例方法,但类方法仍然属于该模块吗?基本上是的,这是我在“类方法如何工作”中解释的“部分。我现在正在写一个更详细的解释。在“为什么Ruby不能自动执行此操作?”下添加了一些额外的解释。模块中的实例方法只有在包含到类中时才真正有用,因此我们希望包含所有这些方法。在第二个示例中(现在)
module N
def self.abc
puts 'basic module'
end
end
class Product < ActiveRecord::Base
include N
end
module M
def self.class_method
"foo"
end
def self.configure_module
# add configuration for this module
end
end
class C
include M
end