非常教程

Ruby 2.4参考手册

语言 | 3Language

Modules

模块在 Ruby 中有两个用途,命名空间和混合功能。

命名空间可以用于通过包或功能组织代码,以将常见名称与其他包的干扰区分开来。例如,IRB 命名空间提供了 irb 功能,可防止通用名称 “Context” 发生冲突。

混合功能允许跨多个类或模块共享常用方法。Ruby 带有 Enumerable 混合模块,它提供了许多基于each方法的枚举方法,而 Comparable 允许根据<=>比较方法比较对象。

请注意,模块和类之间有许多相似之处。除了混合模块的能力之外,以下模块的描述也适用于类。

Module Definition

模块使用module关键字创建:

module MyModule
  # ...
end

模块可以重新打开任意次数以添加,更改或删除功能:

module MyModule
  def my_method
  end
end

module MyModule
  alias my_alias my_method
end

module MyModule
  remove_method :my_method
end

重新打开类是 Ruby 的一个非常强大的功能,但最好只重新打开你自己的类。重新打开您不属于自己的课程可能会导致命名冲突或难以诊断错误。

Nesting

模块可以嵌套:

module Outer
  module Inner
  end
end

许多包创建一个最外层的模块(或类)来为其功能提供一个名称空间。

您也可以使用::提供的外部模块(或类)定义内部模块:

module Outer::Inner::GrandChild
end

请注意,这将引发NameError如果OuterOuter::Inner尚未确定。

这种风格的好处是允许作者减少缩进量。而不是3个级别的缩进,只有一个是必要的。但是,对于使用此语法创建名称空间而不是更详细的语法,常量查找的范围不同。

Scope

self

self指的是定义当前范围的对象。self在输入不同的方法或定义新的模块时会改变。

Constants

可访问的常量根据模块嵌套而不同(使用哪种语法来定义模块)。在下面的例子中,A::Z可以从 B 访问常量,因为 A 是嵌套的一部分:

module A
  Z = 1

  module B
    p Module.nesting #=> [A::B, A]
    p Z #=> 1
  end
end

但是,如果您使用::定义A::B而不嵌套它A,则会引发 NameError 异常,因为嵌套不包括A

module A
  Z = 1
end

module A::B
  p Module.nesting #=> [A::B]
  p Z #=> raises NameError
end

如果在顶层定义了一个常量,则可以在其之前::引用它:

Z = 0

module A
  Z = 1

  module B
    p ::Z #=> 0
  end
end

Methods

有关方法定义文档,请参阅方法的语法文档。

类方法可以直接调用。(这有点令人困惑,但模块上的方法通常被称为“类方法”,而不是“模块方法”。另请参阅模块 #module_function,它可以将实例方法转换为类方法。)

当一个类方法引用一个常量时,它使用与在该方法之外引用它相同的规则,因为范围相同。

在模块中定义的实例方法仅在包含时才可调用。这些方法可以访问通过祖先列表包含的常量:

module A
  Z = 1

  def z
    Z
  end
end

include A

p self.class.ancestors #=> [Object, A, Kernel, BasicObject]
p z #=> 1

Visibility

Ruby 有三种可见性。默认是public。公共方法可以从任何其他对象调用。

第二个可见性是protected。当调用受保护的方法时,发送者必须是接收者的子类,或者接收者必须是发送者的子类。否则会引发 NoMethodError。

受保护的可见性最常用于定义==和其他比较方法,其中作者不希望将任何对象的状态公开给任何调用者,并希望仅将其限制为继承的类。

这里是一个例子:

class A
  def n(other)
    other.m
  end
end

class B < A
  def m
    1
  end

  protected :m

end

class C < B
end

a = A.new
b = B.new
c = C.new

c.n b #=> 1 -- C is a subclass of B
b.n b #=> 1 -- m called on defining class
a.n b # raises NoMethodError A is not a subclass of B

第三个可见性是private。私人方法可能不会被接收方调用,甚至不会self。如果使用接收方调用私有方法,则会引发 NoMethodError。

aliasundef

您也可以使用别名或不定义方法,但这些操作不限于模块或类。查看文档的其他语法部分。

每个类也是一个模块,但与模块不同,一个类可能不会混入另一个模块(或类)。就像一个模块一样,一个类可以用作命名空间。一个类还从它的超类继承了方法和常量。

定义一个类

使用class关键字创建一个类:

class MyClass
  # ...
end

如果你不提供超类,你的新类将继承 Object。您可以继续使用不同的类,<然后使用类名称:

class MySubclass < MyClass
  # ...
end

有一个特殊的 BasicObject 类被设计成一个空白类,并且包含最少的内置方法。您可以使用 BasicObject 创建独立的继承结构。有关更多详细信息,请参阅 BasicObject 文档。

Inheritance

定义在类上的任何方法都可以从它的子类中调用:

class A
  Z = 1

  def z
    Z
  end
end

class B < A
end

p B.new.z #=> 1

常量同样如此:

class A
  Z = 1
end

class B < A
  def z
    Z
  end
end

p B.new.z #=> 1

您可以通过重新定义方法来覆盖超类方法的功能:

class A
  def m
    1
  end
end

class B < A
  def m
    2
  end
end

p B.new.m #=> 2

如果你想从一个方法调用超类功能,使用super

class A
  def m
    1
  end
end

class B < A
  def m
    2 + super
  end
end

p B.new.m #=> 3

在没有任何参数的情况下super使用给子类方法的参数。不发送参数给超类方法使用super()。要向超类方法发送特定参数,请手动提供它们super(2)

super 可以在子类方法中多次调用。

对象的单例类(也称为元类或特征类)是仅为该实例保存方法的类。你可以class << object像这样访问对象的单例类:

class C
end

class << C
  # self is the singleton class here
end

大多数情况下,你会看到像这样访问的单例类:

class C
  class << self
    # ...
  end
end

这允许在类(或模块)上定义方法和属性而无需编写def self.my_method

既然你可以打开任何对象的单例类,这意味着这个代码块:

o = Object.new

def o.my_method
  1 + 1
end

相当于这个代码块:

o = Object.new

class << o
  def my_method
    1 + 1
  end
end

两个对象都会由my_method返回2

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