非常教程

Ruby 2.4参考手册

语言 | 3Language

Methods

方法实现程序的功能。这是一个简单的方法定义:

def one_plus_one
  1 + 1
end

方法定义由def关键字,方法名称,方法的主体,return值和end关键字组成。当被调用时,该方法将执行该方法的主体。此方法返回2

本节仅介绍定义方法。另请参阅调用方法的语法文档。

方法名称

方法名称可能是操作员之一,或者必须以8位设置开始字母或字符。它可能包含字母,数字,_(下划线或下划线)或八位设置的字符。约定是使用下划线来分隔多字方法名称中的单词:

def method_name
  puts "use underscores to separate words"
end

Ruby 程序必须使用 US-ASCII 兼容字符集编写,例如 UTF-8,ISO-8859-1等。在这些字符集中,如果设置了8位,则表示扩展字符。Ruby 允许方法名称和其他标识符包含这些字符。Ruby 程序不能包含一些像 ASCII NUL(\x00)这样的字符。

以下是有效的 ruby 方法的例子:

def hello
  "hello"
end

def こんにちは
  puts "means hello in Japanese"
end

通常方法名称与 US-ASCII 兼容,因为键入它们的键存在于所有键盘上。

方法名称可以以!(bang 或感叹号),?(问号)或=等号结尾。

bang 方法(!在方法名称末尾)与其他方法一样被调用和执行。但是,按照惯例,带有感叹号或爆炸的方法被认为是危险的。在 ruby 核心库中,危险的方法意味着当一个方法以爆炸(!)结束时,它表明不像其非爆炸等价物,永久修改其接收器。几乎总是,ruby 核心库将有一个不会修改接收者!的每一个爆炸方法(方法名称结束!)的非爆炸对象(方法名称不会结束)。这个约定对于 ruby 核心库来说通常是正确的,但是对于其他 ruby 库可能会或可能不会。

按照惯例以问号结尾的方法返回布尔值,但它们不一定总是返回正确truefalse。通常,他们会返回一个对象来表示真值(或“真值”)。

以等号结尾的方法表示分配方法。对于赋值方法,返回值被忽略,而是返回参数。

这些是各种 ruby 运营商的方法名称。这些运营商中的每一个只接受一个参数。操作员之后是操作员的典型用途或名称。为操作符创建一个可选的含义可能会导致混淆,因为用户期望 plus 加上东西,减去减去东西等。另外,不能改变操作符的优先级。

+

-

减去

*

**

指数

/

%

模数除法,字符串#%

&

AND

^

XOR (exclusive OR)

>>

右移

<<

左移,追加

==

等于

!=

不等于

===

相等。请参阅对象#===

=~

模式匹配。(不仅适用于正则表达式)

!~

不匹配

<=>

比较 aka 太空船操作员。看比较

<

less-than

<=

less-than or equal

>

greater-than

>=

大于或等于

要定义一元方法 minus,plus,tilde和not(!),请使用@as +@或in !@

class C
  def -@
    puts "you inverted this object"
  end
end

obj = C.new

-obj # prints "you inverted this object"

一元方法接受零参数。

另外,对于元件的参考和分配方法可以被定义为:[][]=分别。两者都可以带一个或多个参数,而元素引用可以不带任何参数。

class C
  def [](a, b)
    puts a + b
  end

  def []=(a, b, c)
    puts a * b + c
  end
end

obj = C.new

obj[2, 3]     # prints "5"
obj[2, 3] = 4 # prints "10"

返回值

默认情况下,方法返回在方法主体中评估的最后一个表达式。在上面的例子中,最后(也是唯一)的表达式是简单的总和1 + 1return关键字可用于使之明确,一个方法返回一个值。

def one_plus_one
  return 1 + 1
end

它也可以用来在最后一个表达式求值之前返回一个方法。

def two_plus_two
  return 2 + 2
  1 + 1  # this expression is never evaluated
end

请注意,对于赋值方法,返回值将始终被忽略。相反,参数将被返回:

def a=(value)
  return 1 + value
end

p(a = 5) # prints 5

范围

定义方法的标准语法:

def my_method
  # ...
end

将该方法添加到类中。您可以使用class关键字在特定类上定义实例方法:

class C
  def my_method
    # ...
  end
end

可以在另一个对象上定义一个方法。你可以像这样定义一个“类方法”(一个在类中定义的方法,而不是类的一个实例):

class C
  def self.my_method
    # ...
  end
end

然而,这仅仅是 Ruby 中一种更强大的语法能力的特例,它可以将方法添加到任何对象中。类是对象,因此添加类方法只是将方法添加到 Class 对象。

将方法添加到对象的语法如下所示:

greeting = "Hello"

def greeting.broaden
  self + ", world!"
end

greeting.broaden # returns "Hello, world!"

self是一个关键字,用于引用编译器正在考虑的当前对象,这可能会使得self在定义类方法时更加清晰。事实上,在hello类中添加方法的例子String可以这样重写:

def String.hello
  "Hello, world!"
end

这样定义的方法称为“单例方法”。broaden将只存在于字符串实例上greeting。其他字符串不会有broaden

重写

当 Ruby 遇到def关键字时,如果方法已经存在,它不会认为它是错误的:它只是重新定义它。这被称为覆盖。与扩展核心类相似,这是一种潜在的危险能力,应谨慎使用,因为它可能会导致意想不到的结果。例如,考虑这个 irb 会话:

>> "43".to_i
=> 43
>> class String
>>   def to_i
>>     42
>>   end
>> end
=> nil
>> "43".to_i
=> 42

这将有效地破坏任何使用该方法String#to_i从字符串解析数字的代码。

参数

一个方法可以接受参数。参数列表在方法名称后面:

def add_one(value)
  value + 1
end

当被调用时,add_one方法的用户必须提供一个参数。参数是方法体中的局部变量。然后该方法将为此参数添加一个并返回值。如果给定1此方法将返回2

参数周围的括号是可选的:

def add_one value
  value + 1
end

多个参数用逗号分隔:

def add_values(a, b)
  a + b
end

被调用时,参数必须按照正确的顺序提供。换句话说,论据是有争议的。

默认值

参数可能有默认值:

def add_values(a, b = 1)
  a + b
end

默认值不需要首先显示,但具有默认值的参数必须组合在一起。还行吧:

def add_values(a = 1, b = 2, c)
  a + b + c
end

这会引发一个 SyntaxError:

def add_values(a = 1, b, c = 1)
  a + b + c
end

数组分解

您可以使用参数中的额外括号分解(从数组中解压缩或提取值):

def my_method((a, b))
  p a: a, b: b
end

my_method([1, 2])

这打印:

{:a=>1, :b=>2}

如果参数在数组中有额外的元素,它们将被忽略:

def my_method((a, b))
  p a: a, b: b
end

my_method([1, 2, 3])

这与上面的输出相同。

您可以使用 *来收集剩余的参数。这将数组分为第一个元素和其余的元素:

def my_method((a, *b))
  p a: a, b: b
end

my_method([1, 2, 3])

这打印:

{:a=>1, :b=>[2, 3]}

如果它响应 to_ary,则参数将被分解。如果可以使用对象代替 Array,则只应定义 to_ary。

使用内部括号仅使用发送的参数之一。如果参数不是数组,则它将被分配给分解中的第一个参数,分解中的其余参数将为nil

def my_method(a, (b, c), d)
  p a: a, b: b, c: c, d: d
end

my_method(1, 2, 3)

这打印:

{:a=>1, :b=>2, :c=>nil, :d=>3}

你可以任意嵌套分解:

def my_method(((a, b), c))
  # ...
end

Array/Hash 参数

在参数前加上一个参数,可以*将任何剩余的参数转换为一个数组:

def gather_arguments(*arguments)
  p arguments
end

gather_arguments 1, 2, 3 # prints [1, 2, 3]

数组参数必须是最后一个位置参数,它必须出现在任何关键字参数之前。

如果在所有位置参数之后由调用方发送哈希,则数组参数将捕获哈希作为最后一个条目。

gather_arguments 1, a: 2 # prints [1, {:a=>2}]

但是,只有当方法没有声明任何关键字参数时才会发生这种情况。

def gather_arguments_keyword(*positional, keyword: nil)
 p positional: positional, keyword: keyword
end

gather_arguments_keyword 1, 2, three: 3
#=> raises: unknown keyword: three (ArgumentError)

另外请注意,*可以使用 bare 来忽略参数:

def ignore_arguments(*)
end

关键字参数

关键字参数与具有默认值的位置参数相似:

def add_values(first: 1, second: 2)
  first + second
end

任意关键字参数将被接受**

def gather_arguments(first: nil, **rest)
  p first, rest
end

gather_arguments first: 1, second: 2, third: 3
# prints 1 then {:second=>2, :third=>3}

当调用带有关键字参数的方法时,参数可以以任何顺序出现。如果调用者发送未知关键字参数,则引发 ArgumentError。

混合关键字参数和位置参数时,所有位置参数必须出现在任何关键字参数之前。

块参数

块参数由&最后指示并且必须最后一个:

def my_method(&my_block)
  my_block.call(self)
end

大多数情况下,块参数用于将块传递给另一个方法:

def each_item(&block)
  @items.each(&block)
end

如果您只打算调用该块,并且不会以其他方式处理该块或将其发送到另一种方法,yield而不使用明确的块参数,则为首选。此方法等同于本节中的第一种方法:

def my_method
  yield self
end

使用 yield 来调用 block 参数也有性能优势。当一个块参数被分配给一个变量时,一个 Proc 对象被创建并保存该块。当使用 yield 时,这个 Proc 对象不会被创建。

如果您只需要使用该块,则有时可以使用 Proc.new 从传递给您的方法的块创建一个 proc。有关更多详细信息,请参阅 Proc.new。

异常处理

方法有一个隐含的异常处理块,所以你不需要使用beginend处理异常。这个:

def my_method
  begin
    # code that may raise an exception
  rescue
    # handle exception
  end
end

可写成:

def my_method
  # code that may raise an exception
rescue
  # handle exception
end

如果您希望仅拯救部分方法的异常,请使用beginend。有关更多详细信息,请参阅异常处理页面。

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