Ruby中的include和require有什么区别?


Answers:


543

Ruby中的“ include”和“ require”有什么区别?

回答:

include和require方法的作用截然不同。

require方法可以完成大多数其他编程语言所包含的功能:运行另一个文件。它还会跟踪您过去所需的内容,并且不需要两次相同的文件。要运行没有此附加功能的另一个文件,可以使用load方法。

include方法将从另一个模块中获取所有方法,并将它们包括到当前模块中。与require相比,这是语言级别的事情,而不是文件级别的事情。include方法是使用其他模块(通常称为混合)“扩展”类的主要方法。例如,如果您的类定义了方法“ each”,则可以包括mixin模块Enumerable,并且它可以充当集合。由于include动词在其他语言中的用法非常不同,因此可能会造成混淆。

资源

因此,如果您只想使用模块,而不是扩展它或进行混入,那么您将要使用require

奇怪的是,Ruby的require类似于C中的include,而Ruby的include是几乎没有像C的include


45
实际上,C的include并不会按要求加载文件,而是将#include行替换为文件的内容。包含的文件不必为“ header”,#include不必位于文件的开头,但可以位于任何地方,例如在类或方法定义中。这意味着您可以通过在文件中编写一些方法并将其包含在类代码中来在C ++中进行混合,这正是您在ruby中所做的。因此,尽管实际上这不是C语言中的普遍做法,但它们相距不远。
mb14 2013年

13
通过包含示例可以使该答案受益。
Travis Bear

12
mb14的注释暗含了这一点,但需要明确说明:与答案相反,require并不会 “运行”文件,而是将其视为包含文件的一部分进行加载。这可能看起来像语义挑剔,但实际上是一个相当重要的区别。
Lonny Eachus 2014年

很好的解释。感谢您在最后一条语句中指出:“奇怪的是,Ruby的需求类似于C的包含,而Ruby的包含几乎没有C的包含。”
ArtSabintsev 2014年

1
@GregSchmit:include在Ruby中只是继承。class C; include M end使M的超类C和的超类(以前的)超CM。我不认为C是include通过继承来工作的,我认为这是简单的文本/词法替换。
约尔格W¯¯米塔格

100

如果使用模块,则意味着将所有方法都带入类中。如果您extend使用带有模块的类,则意味着您将“引入”模块的方法作为方法。如果您include使用模块类,则意味着您将“引入”模块的方法作为实例方法。

例如:

 module A
   def say
     puts "this is module A"
   end
 end

 class B
   include A
 end

 class C
   extend A
 end

B.say => B:Class的未定义方法“ say”

B.new.say =>这是模块A

C.say =>这是模块A

C.new.say => C:Class的未定义方法“ say”


23
我认为这不能回答问题,但这是我在寻找的=)
Ciro Santilli郝海东冠状病六四事件法轮功

2
这实际上并没有回答require和之间include有什么区别的问题。

94

从元编程Ruby书中,

require()方法与十分相似load(),但是其目的不同。您用于load()执行代码,并 require()用于导入库。


73
不赞成与您的答案中的另一种语言比较:)
Stevo

否决了以下问题而不提供答案的投票:“是否只想使用班级模块中的方法?”
2016年

57

这是一个很好的解释在这里

[简单的答案是:要求和包含本质上是无关的。

“ require”类似于C包含,这可能引起新手混淆。(一个显着的区别是,完成需求后,所需文件中的本地文件“蒸发”。)

Ruby include与C include完全不同。include语句将模块“混入”到一个类中。这是多重继承有限形式。从本质上讲,一个包含的模块在包含它的事物上赋予了“是”关系。

重点已添加。


7

您是否尝试require过模块?结果如何?你试一试:

MyModule = Module.new
require MyModule # see what happens

不需要模块,仅包括模块!


这里的说法是不正确的。可能需要模块。TypeError如果将单词Module改为,则运行上述代码的任何人都会发现他们得到相同的结果()Class
pjd

7

Ruby 1.9编程开始

在继续之前,我们将对include语句提出几点要点。首先,它与文件无关。C程序员使用称为#include的预处理程序指令在编译过程中将一个文件的内容插入另一个文件。Ruby的include语句只是对模块的引用。如果该模块在单独的文件中,则在使用include之前,必须使用require(或其不太常用的表亲,load)将该文件拖入其中。其次,Ruby include不能简单地将模块的实例方法复制到类中。而是从类对所包含的模块进行引用。如果多个类包含该模块,则它们都将指向同一事物。如果您更改了模块内方法的定义,即使您的程序正在运行,


3

包含当您将模块包含到类中(如下所示)时,就好像您采用了模块中定义的代码并将其插入到类中的“包含”位置一样。它允许'mixin'行为。例如,如果有多个类需要在模块中使用相同的代码,则可以使用它来使代码干燥(DRY)以避免重复。

加载加载方法几乎与require方法类似,不同之处在于它无法跟踪该库是否已加载。因此,可以多次加载库,而且在使用加载方法时,必须指定库文件名的“ .rb”扩展名。

Require require方法允许您加载一个库,并防止它被加载多次。如果您在第一次之后尝试加载相同的库,则require方法将返回“ false”。仅在要加载的库是在单独的文件中定义的情况下才需要使用require方法,通常是这种情况。

您可以选择使用此 http://ionrails.com/2009/09/19/ruby_require-vs-load-vs-include-vs-extend/


3

以下是require和include之间的一些基本区别:

要求:

  1. Require从文件系统读取文件,进行分析,保存到内存中,然后在给定位置运行它,这意味着即使您在脚本运行时甚至要更改任何内容,该更改也无法反映出来。
  2. 我们需要文件名而不是模块名。
  3. 它通常用于库和扩展。

包括:

  1. 当您将模块包含在类中时,其行为就像您将模块中定义的代码插入类中一样。
  2. 我们包括模块名称,而不是文件名称。
  3. 它通常用于清除代码并删除代码中的重复项。

2
require(name)

它将返回布尔值true / false

作为参数传递给require的名称,ruby将尝试在您的加载路径中查找具有该名称的源文件。如果您在第一次之后尝试加载相同的库,则require方法将返回“ false”。仅当要加载的库在单独的文件中定义时,才需要使用require方法。因此,它将跟踪该库是否已加载。

include module_name

假设您需要在两个不同的类中具有某些方法。然后,您不必在两个类中都编写它们。相反,您可以做的是在模块中定义它。然后将此模块包含在其他类中。它由Ruby提供,只是为了确保DRY原理。它用于使您的代码干燥以避免重复


2

包括

当您include将模块插入类时,就好像您将模块中定义的代码插入到类中的“包含”其中一样。它允许'mixin'行为。例如,如果有多个类需要在模块中使用相同的代码,则可以使用它来使代码干燥(DRY)以避免重复。

module Log 
  def class_type
    "This class is of type: #{self.class}"
  end
end

class TestClass 
  include Log 
  # ... 
end

tc = TestClass.new.class_type # -> success
tc = TestClass.class_type # -> error

要求

require方法允许您加载库,并防止它被加载多次。如果您在第一次之后尝试加载相同的库,则require方法将返回“ false”。仅在要加载的库是在单独的文件中定义的情况下才需要使用require方法,通常是这种情况。

因此,它将跟踪该库是否已加载。您也不需要指定库文件名的“ .rb”扩展名。这是一个如何使用require的示例。将require方法放在“ .rb”文件的最顶部:

加载

load方法几乎与require方法类似,不同之处在于它不跟踪是否已加载该库。因此,可以多次加载库,而且在使用加载方法时,必须指定库文件名的“ .rb”扩展名。

延伸

当使用extend方法而不是include时,您将模块的方法添加为类方法,而不是实例方法。

module Log 
  def class_type
    "This class is of type: #{self.class}"
  end
end

class TestClass 
  extend Log 
  # ... 
end

tc = TestClass.class_type

2

'加载'-插入文件的内容。(每次调用文件时解析文件)

'Require'-插入文件解析的内容。(文件解析一次并存储在内存中)

'include'-将模块包含在类中,并且可以将模块内部的方法用作类的实例方法

'扩展'-将模块包含在类中,并且可以将模块内部的方法用作类方法

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.