翻译 基础 Ruby 中 Include, Extend, Load, Require 的使用区别

skpark1987 · 2015年05月22日 · 最后由 bluesky0318 回复于 2019年08月09日 · 18064 次阅读
本帖已被设为精华帖!

原文链接: Ruby Require VS Load VS Include VS Extend

Include

如下例当你 Include 一个模块到某个类时, 相当于把模块中定义的方法插入到类中。它允许使用 mixin。它用来 DRY 你的代码, 避免重复。例如, 当你有多个类时, 需要相同的函数时, 可以把函数定义到 module 中, 进行 include。 下例假设模块 Log 和类 TestClass 在相同的.rb 文件。如果它们存在于多个文件, 则需要使用 load 或 require 导入文件。

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

class TestClass 
  include Log 
end

tc = TestClass.new.class_type
puts tc #This class is of type: TestClass

Extend

当你使用 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
puts tc  # This class is of type: TestClass

当你在类中使用 Extend 来代替 Include, 如果你实例化 TestClass 并调用 class_type 方法时,你将会得到 NoMethodError。再一次强调, 使用 Extend 时方法是类方法。

Require

Require 方法允许你载入一个库并且会阻止你加载多次。当你使用 require 重复加载同一个 library 时,require 方法 将会返回 false。当你要载入的库在不同的文件时才能使用 require 方法。下例将演示 require 的使用方式。

文件 test_library.rb 和 test_require.rb 在同一个目录下。

# test_library.rb
puts " load this libary "
# test_require.rb
puts (require './test_library')
puts (require './test_library')
puts (require './test_library')
# 结果为
#  load this libary 
# true
# false
# false

Load

Load 方法基本和 require 方法功能一致,但它不会跟踪要导入的库是否已被加载。因此当重复使用 load 方法时,也会载入多次。大部分情况你都会使用 require 来代替 load。但当你需要每次都要加载时候你才会使用 load, 例如模块的状态会频繁地变化, 你会使用 load 进行加载,获取最新的状态。

puts load "./test_library.rb"  #在这里不能省略 .rb, require可以省略
puts load "./test_library.rb" 
puts load "./test_library.rb" 
#结果
# load this libary
#true
# load this libary
#true
# load this libary
#true

被标题的 import 引进来了

谢谢,这对我很有用 !

顺便在讲讲autoload呗~

#1 楼 @lululau 哈哈 java_import & import for JRuby

我也是被 import 吸引进来的!!!

没有 import 啊啊啊啊

import 在纳尼……

复习了。和 PHP 的有所不同。如果加载的文件不存在,会分别出现什么信息呢?

被 import 吸引进来的。。。。。小吓一跳。。。。。

楼主不打算去掉标题中的 import 吗

内容有点乱,load 和 require 是 Kernel 提供的类加载接口,extend 和 include 是互相引用的接口,有本质区别

不错的分享。简单几句,就把事情说得比较清楚了。

088pause 回复

这样说会不会就统一了?不管是对象还是类,使用 extend,module 中的普通方法都成为了它们的单件方法,因为类方法也是单件方法的一种。

讲得很清楚了,谢谢

另外从 Ruby 程序员修炼之道一文中也提到,load 可以辨识当前工作目录,require 确不行,比如 load "xxx.rb"可正常编译,而 require "xx.rb"不可以编译通过,需要改为 require "./xx.rb"或者全路径模式,还有一个 require_relative 也很好用

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册