【问题标题】:What is the difference between include and require in Ruby?Ruby 中的 include 和 require 有什么区别?
【发布时间】:2010-09-24 00:09:02
【问题描述】:

我的问题类似于“What is the difference between include and extend in Ruby?”。

Ruby 中的require 和include 有什么区别?如果我只想在我的班级中使用模块中的方法,我应该require 它还是include 它?

【问题讨论】:

标签: ruby include require


【解决方案1】:

有什么区别 Ruby 中的“包含”和“要求”?

答案:

include 和 require 方法可以 非常不同的东西。

require 方法的作用包括 在大多数其他编程中 语言:运行另一个文件。它也是 跟踪您在 过去并且不需要相同的文件 两次。运行另一个文件而不 这个添加的功能,你可以使用 加载方法。

include 方法获取所有 来自另一个模块的方法和 将它们包含在当前模块中。 这是语言级别的事情 与文件级的东西相反 要求。包含方法是 “扩展”类的主要方式 其他模块(通常称为 混音)。例如,如果您的班级 定义方法“每个”,你可以 包括 mixin 模块 Enumerable 它可以作为一个集合。这 可能会因为包含动词而令人困惑 在其他方面的使用方式非常不同 语言。

Source

因此,如果您只想使用一个模块,而不是扩展它或进行混合,那么您将希望使用require。

奇怪的是,Ruby 的require 类似于C 的include,而Ruby 的include 几乎与C 的include 完全不同。

【讨论】:

  • 事实上 C 的 include 并不像需要那样加载文件,而是用文件的内容替换 #include 行。包含的文件不必是“标题”,#include 不必位于文件的开头,而是可以在任何地方,例如在类中甚至方法定义中。这意味着您可以通过在文件中编写一些方法并将其包含在类的代码中来在 C++ 中进行 mixin,这正是您在 ruby​​ 中所做的。所以它们并没有那么远,尽管这在 C 语言中确实不是一种常见的做法。
  • 这个答案可以通过包含示例来受益。
  • mb14 的评论暗示了这一点,但它明确指出:与答案所说的相反,require 不是“运行”文件,而是像加载它一样加载它包含文件的一部分。这可能看起来像是语义上的吹毛求疵,但实际上这是一个相当重要的区别。
  • @LonnyEachus:这是错误的。 require 只是运行文件。时期。特别是,这意味着如果您将 require 调用放在类声明中,文件中的代码将不会成为该类的一部分,如果您将 require 调用放在方法定义,文件中的代码将不成为该方法的一部分,如果您将require调用放在模块声明中,文件中的代码将不 成为该模块的一部分,依此类推。它甚至没有成为require 调用所在文件的一部分。Stack Overflow 上有很多问题......
  • @GregSchmit: include 在 Ruby 中只是继承。 class C; include M end 使M 成为C 的超类,而C 的(前)超类成为M 的超类。我不认为 C 的 include 通过继承工作,我认为这是简单的文本/词汇替换。
【解决方案2】:

有一个很好的解释here:

[The] 简单的答案是 require 和 include 本质上是不相关的。

"require" 类似于 C 的 include,可能会引起新手混淆。 (一个显着的区别是所需文件中的本地人“蒸发” 当要求完成时。)

Ruby include 与 C 中的 include 完全不同。 include 语句将一个模块“混合”到一个类中。这是一个有限的形式 多重继承。包含的模块实际上赋予了“is-a” 包括它在内的事物的关系。

添加了重点。

【讨论】:

  • 模块导入不像文件包含那样,因为它与程序的外部源表示无关。它更像这里的include。命名空间、包和类类型对象都可以被视为特殊的环境,它们通常保存名称绑定。 (考虑 these differences 和 Kernel 的 $import!。还要注意 Racket 的环境是在命名空间中实现的。)
【解决方案3】:

来自元编程 Ruby 书,

require() 方法与load() 非常相似,但它适用于 不同的目的。你使用load() 来执行代码,你使用 require() 导入库。

【讨论】:

  • 赞成在您的回答中不与另一种语言进行比较:)
  • 对在以下问题的上下文中不提供答案投反对票:“如果我只想在我的班级中使用模块中的方法?”
【解决方案4】:

如果您使用的是模块,这意味着您将所有方法都带入您的类。 如果您extend 一个带有模块的类,这意味着您将模块的方法“引入”为 class 方法。 如果您 include 一个带有模块的类,这意味着您将模块的方法“引入”为 instance 方法。

前:

 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 的未定义方法“说”

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

C.say => 这是模块 A

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

【讨论】:

  • 我认为这并不能回答问题,但这是我要找的 =)
  • 这实际上并没有回答require 和include 之间的区别是什么的问题。
【解决方案5】:

你有没有试过require一个模块?结果如何?试试看:

MyModule = Module.new
require MyModule # see what happens

模块不是必需的,只有包括在内!

【讨论】:

  • 这里的断言不正确。可能需要模块。如果将单词 Module 更改为 Class,任何运行上述代码的人都会发现他们收到相同的结果 (TypeError)。
【解决方案6】:

来自Ruby 1.9 编程

在继续之前,我们将对 include 语句提出几点意见。首先,它有 与文件无关。 C 程序员使用称为#include 的预处理器指令 在编译期间将一个文件的内容插入另一个文件。 Ruby 包含语句 简单地引用一个模块。如果该模块位于单独的文件中,则必须使用 在使用 include 之前需要(或其不太常用的表亲,加载)将该文件拖入。 其次,Ruby 包含不简单地将模块的实例方法复制到类中。 相反,它从类中引用包含的模块。如果有多个班级 包括那个模块,它们都会指向同一个东西。如果您更改 a 的定义 模块中的方法,即使您的程序正在运行,所有包含该方法的类 模块将表现出新的行为。

【讨论】:

    【解决方案7】:

    包括 当您将一个模块包含到您的类中时,如下所示,就好像您将模块中定义的代码插入到您“包含”它的类中一样。它允许“混合”行为。它用于干燥您的代码以避免重复,例如,如果模块中有多个类需要相同的代码。

    加载 load 方法与 require 方法几乎一样,只是它不跟踪该库是否已加载。因此可以多次加载一个库,并且在使用加载方法时,您必须指定库文件名的“.rb”扩展名。

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

    你可以喜欢这个 http://ionrails.com/2009/09/19/ruby_require-vs-load-vs-include-vs-extend/

    【讨论】:

      【解决方案8】:
      require(name)
      

      它将返回布尔真/假

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

      include module_name
      

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

      【讨论】:

        【解决方案9】:

        包括

        当你 include 一个模块进入你的班级时,就好像你拿了 在模块中定义的代码并将其插入到类中,其中 你“包括”它。它允许“混合”行为。它用于干燥 您的代码以避免重复,例如,如果有多个 在模块中需要相同代码的类。

        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”,如果 您尝试在第一次之后加载相同的库。要求 仅当您正在加载的库在中定义时才需要使用方法 一个单独的文件,通常是这种情况。

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

        加载

        load 方法几乎和 require 方法一样,只是它没有 跟踪该库是否已加载。所以就是 可以多次加载库,也可以在使用加载时加载 方法,您必须指定库文件名的“.rb”扩展名。

        扩展

        当使用扩展方法而不是包含时,您正在添加 模块的方法作为类方法而不是实例方法。

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

        【讨论】:

          【解决方案10】:

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

          要求:

          1. Require 从文件系统读取文件,对其进行解析,保存到内存并在给定位置运行它,这意味着如果您在脚本运行时更改任何内容,那么该更改将不会反映。
          2. 我们需要文件名,而不是模块名。
          3. 它通常用于库和扩展。

          包括:

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

          【讨论】:

            【解决方案11】:

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

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

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

            'Extend'- 将模块包含到类中,并且可以将模块内的方法用作类方法

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2010-10-10
              • 2023-03-26
              • 1970-01-01
              • 2021-04-21
              • 2011-04-07
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多