非常教程

Ruby 2.4参考手册

语言 | 3Language

Refinements

由于 Ruby 的开放类,您可以重新定义或添加功能到现有的类。这被称为 “monkey patching”。不幸的是,这种变化的范围是全球性的。monkey patching 类的所有用户都会看到相同的更改。这可能会导致意外的副作用或程序中断。

细化旨在减少 monkey patching 对 monkey patching 类的其他用户的影响。精化提供了一种在本地扩展类的方法。

这是一个基本的改进:

class C
  def foo
    puts "C#foo"
  end
end

module M
  refine C do
    def foo
      puts "C#foo in M"
    end
  end
end

首先,C定义一个类。接下来C使用 Module#refine 来创建一个改进。优化只修改类,而不是模块,因此参数必须是类。

Module#refine 创建一个匿名模块,其中包含对该类的更改或优化(C在该示例中)。self在精炼块中是这个匿名模块,类似于 Module#module_eval。

使用以下命令激活优化:

using M

c = C.new

c.foo # prints "C#foo in M"

Scope

您可以在顶层和类和模块内激活细化。您可能无法激活方法范围中的细化。细化被激活直到当前类或模块定义结束,或者直到当前文件的结尾(如果在顶层使用)。

您可以在传递给 Kernel#eval 的字符串中激活优化。优化活动在 eval 字符串的结尾。

精化在范围上是词法。细化仅在调用使用后的范围内有效。使用语句之前的任何代码都不会激活细化。

当控制转移到范围之外时,精化被停用。这意味着如果您需要或加载文件或调用在当前作用域之外定义的方法,则优化将被停用:

class C
end

module M
  refine C do
    def foo
      puts "C#foo in M"
    end
  end
end

def call_foo(x)
  x.foo
end

using M

x = C.new
x.foo       # prints "C#foo in M"
call_foo(x) #=> raises NoMethodError

如果方法在精化处于活动状态的范围中定义,则在调用方法时精化将处于活动状态。这个例子跨越多个文件:

c.rb:

class C
end

m.rb:

require "c"

module M
  refine C do
    def foo
      puts "C#foo in M"
    end
  end
end

m_user.rb:

require "m"

using M

class MUser
  def call_foo(x)
    x.foo
  end
end

main.rb:

require "m_user"

x = C.new
m_user = MUser.new
m_user.call_foo(x) # prints "C#foo in M"
x.foo              #=> raises NoMethodError

由于细化M是活跃m_user.rb在那里MUser#call_foo的定义,也激活时main.rb调用call_foo

由于使用是一种方法,因此只有在调用它时才会激活优化。以下是一些细化M和不活跃的例子。

在一个文件中:

# not activated here
using M
# activated here
class Foo
  # activated here
  def foo
    # activated here
  end
  # activated here
end
# activated here

在课堂上:

# not activated here
class Foo
  # not activated here
  def foo
    # not activated here
  end
  using M
  # activated here
  def bar
    # activated here
  end
  # activated here
end
# not activated here

请注意,如果稍后重新打开 Foo 类,则 M 中的优化不会自动激活。

在评估中:

# not activated here
eval <<EOF
  # not activated here
  using M
  # activated here
EOF
# not activated here

未评估时:

# not activated here
if false
  using M
end
# not activated here

当在同一个模块中定义多个细化时,在细化块内部,当调用细化方法时,来自同一模块的所有细化都将处于活动状态:

module ToJSON
  refine Integer do
    def to_json
      to_s
    end
  end

  refine Array do
    def to_json
      "[" + map { |i| i.to_json }.join(",") + "]"
    end
  end

  refine Hash do
    def to_json
      "{" + map { |k, v| k.to_s.dump + ":" + v.to_json }.join(",") + "}"
    end
  end
end

using ToJSON

p [{1=>2}, {3=>4}].to_json # prints "[{\"1\":2},{\"3\":4}]"

方法查找

在查找CRuby 类检查实例的方法时:

  • 如果优化处于激活状态C,按相反顺序激活:
-  The prepended modules from the refinement for `C`
-  The refinement for `C`
-  The included modules from the refinement for `C`
  • 前置模块 C
  • C
  • 包含的模块 C

如果在任何时候没有发现任何方法,则重复使用超类C

请注意,子类中的方法优先于超类中的优化。例如,如果在/Intege r的细化中定义该方法,则会1 / 2调用原始的 Fixnum#/,因为Fixnum是 Integer 的一个子类,并且在超类 Integer 的细化之前进行搜索。

如果方法foo在细化中定义在 Integer 上,则1.foo调用该方法,因为 Fixnum 上不存在foo方法。

super

super被调用的方法查找检查时:

  • 包含当前课程的模块。请注意,目前的课程可能是一个改进。
  • 如果当前类是一个改进,则方法查找按照上面的“方法查找”部分进行。
  • 如果当前类有一个直接的超类,那么该方法将继续使用超类的上面的方法查找部分。

请注意,super在细化的方法中,即使存在已在相同上下文中激活的另一个细化,也会调用细化类中的方法。

间接方法调用

当使用间接方法访问,如 Kernel#send,Kernel#method 或 Kernel#respond_to?在方法查找过程中,调用者上下文并不满足优化。

这种行为在未来可能会改变。

Ruby 2.4

Ruby 是一种面向对象、命令式、函数式、动态的通用编程语言,是世界上最优美而巧妙的语言。

主页 https://www.ruby-lang.org/
源码 https://github.com/ruby/ruby
版本 2.4
发布版本 2.4.1

Ruby 2.4目录

1.缩略 | Abbrev
2.ARGF
3.数组 | Array
4.Base64
5.基本对象 | BasicObject
6.基准测试 | Benchmark
7.BigDecimal
8.绑定 | Binding
9.CGI
10.类 | Class
11.比较 | Comparable
12.负责 | Complex
13.计算续体 | Continuation
14.覆盖 | Coverage
15.CSV
16.日期 | Date
17.日期时间 | DateTime
18.DBM
19.代理 | Delegator
20.摘要 | Digest
21.Dir
22.DRb
23.编码 | Encoding
24.枚举 | Enumerable
25.枚举 | Enumerator
26.ENV
27.ERB
28.错误 | Errors
29.Etc
30.期望值 | Exception
31.错误类 | FalseClass
32.Fiber
33.Fiddle
34.文件 | File
35.文件实用程序 | FileUtils
36.查找 | Find
37.浮点 | Float
38.Forwardable
39.GC
40.GDBM
41.GetoptLong
42.Hash
43.Integer
44.IO
45.IPAddr
46.JSON
47.Kernel
48.语言 | 3Language
49.记录 | Logger
50.编排 | Marshal
51.MatchData
52.数学 | Math
53.矩阵 | Matrix
54.方法 | Method
55.模型 | Module
56.监控 | Monitor
57. 互斥 | Mutex
58.Net
59.Net::FTP
60.Net::HTTP
61.Net::IMAP
62.Net::SMTP
63.NilClass
64.数字 | Numeric
65.对象 | Object
66.ObjectSpace
67.Observable
68.Open3
69.OpenSSL
70.OpenStruct
71.OpenURI
72.OptionParser
73.路径名 | Pathname
74.完整输出 | PrettyPrint
75.Prime
76.Proc
77.过程 | Process
78.PStore
79.PTY
80.队列 | Queue
81.随机 | Random
82.范围 | Range
83.合理的 | Rational
84.Readline
85.Regexp
86.Resolv
87.Ripper
88.RubyVM
89.Scanf
90.SDBM
91.SecureRandom
92.Set
93.Shell
94.信号 | Signal
95.Singleton
96.套接字 | Socket
97.字符串 | String
98.StringIO
99.StringScanner
100.结构 | Struct