Ruby 方法

什么是方法以及我们为什么需要它

经常会有一段代码需要在程序中多次执行。大多数编程语言中有一个称为过程的功能,而不是一遍又一遍地编写那段代码,它允许你将公共代码提取到一个地方。

在 Ruby 中,我们称之为方法。在我们可以使用一个方法之前,我们必须首先用保留字 def 定义它。在 def 之后我们给我们的方法定义一个名字。在方法定义的最后,我们使用保留字 end 来表示它的完成。这是名为 say 的方法定义的示例:

def say# 方法体在这里
end

方法主体中有一条注释,用于向你显示方法定义的逻辑将转到的位置。为什么我们需要一个名为 say 的方法?当然!假设我们在名为 say.rb.。

创建此文件并键入这些示例。

# say.rbputs "hello"
puts "hi"
puts "how are you"
puts "I'm fine"

注意我们是如何重复 puts 多次的。我们想要一个地方,我们可以使用 puts 将我们想要的信息发送到那个地方。让我们创建一个方法定义来做到这一点。

# say.rbdef say(words)puts words
endsay("hello")
say("hi")
say("how are you")
say("I'm fine")

乍一看,这似乎很愚蠢,因为我们没有保存任何代码行,实际上添加了更多代码。但是我们所做的是提取了打印文本的逻辑,我们的程序可以有更多的灵活性。

我们通过键入其名称并传入参数来调用(或调用)该方法。你会注意到方法定义中,在 say 之后有一个 (words)。这就是所谓的参数。当你拥有方法定义范围之外的数据,但你需要在方法定义内访问它时,将使用参数。如果方法定义不需要访问任何外部数据,则不需要定义任何参数。

术语方法调用来指代调用方法。

你可以随意命名参数,但正如我们之前所说的,优秀程序员的目标始终是为事物赋予有意义且明确的名称。我们命名参数 words 是因为该 say 方法需要传入一些单词,因此它知道该说什么!参数是发送到方法调用以进行修改或用于返回特定结果的信息片段。我们在调用方法时将参数 “传递” 给它。在这里,我们使用一个参数来传递我们想要在 say 方法定义中使用的单词或单词串。当我们将这些词传递给方法定义时,它们被分配给局部变量 words,我们可以在方法定义中随意使用它们。请注意,words 局部变量的范围在方法定义级别;也就是说,你不能在 say 方法定义之外引用这个局部变量。

当我们调用 时 say(“hello”),我们将字符串 “hello” 作为参数传入 words。然后执行方法定义中的代码,并使用 words 评估为 “hello” 的局部变量。

方法给我们带来的好处之一是能够在一个地方进行更改,从而影响我们程序中的许多地方。假设我们想在发送给 say 方法的每个字符串的末尾添加一个 . 。我们只需要在一个地方进行更改。

def say(words)puts words + '.'    ## <= We only make the change here!
endsay("hello")
say("hi")
say("how are you")
say("I'm fine")

使用 ruby say.rb 终端中的命令运行此代码以查看结果。我们现在已经在每一行添加了一个.,我们只需要在我们的程序中添加一次。现在你开始看到方法的力量。

默认参数

当你定义方法时,你可能希望构造方法定义,使其始终有效,无论是否给定参数。让我们 say 再次重构我们的方法定义,以便我们可以分配一个默认参数,以防调用者不发送任何参数。

# say.rbdef say(words='hello')puts words + '.'
endsay()
say("hi")
say("how are you")
say("I'm fine")

你会注意到 say() 打印 hello.到控制台。我们提供了一个默认参数,每当我们的方法在没有任何参数的情况下被调用时都会使用它。好的!

可选括号

许多 Ruby 专家在调用方法作为样式选择时会省略括号。例如,say() 可以重写为 say. 使用参数,而不是 say(“hi”),它可能只是 say “hi”。这会导致更流畅的代码阅读,但有时可能会令人困惑。在阅读 Ruby 时请记住这一点;它可以在局部变量和方法名称之间进行棘手的破译!

方法定义和局部变量范围

在进入下一个关于方法的主题之前,让我们花点时间讨论一下方法定义中局部变量作用域的概念。方法定义在常规执行流程之外创建自己的范围。这就是方法定义中的局部变量不能从方法定义外部引用的原因。这也是方法定义中的局部变量无法访问方法定义之外的数据的原因(除非数据作为参数传入)。

让我们用下面的例子来实践这个概念:

a = 5def some_methoda = 3
endputs a

a的值是多少?仍然是 5,因为方法定义创建了它们自己的范围,完全在执行流程之外。

在处理局部变量作用域问题时,请确保不要将方法调用与块和方法定义混淆。乍一看,它们可能看起来很相似,但它们并不相同。当涉及到局部变量作用域时,它们有不同的行为。

# 在 Block 中进行方法调用
[1, 2, 3].each do |num|puts num
end# 方法定义def print_num(num)puts num
end

obj.method 或方法 (obj)

我们将在本书中讨论两种方法来调用方法。该 some_method(obj) 格式是当你发送参数的方法调用; 在前面的例子中,obj 是传递给 some_method 方法的参数。有时,你会看到使用显式调用者调用的方法,如下所示 a_caller.some_method(obj)。现在最好将之前的代码视为 some_method 修改 a_caller. 你现在必须记住调用方法所需的方式。

改变调用者

有时,在调用方法时,参数可以永久更改。我们称之为 mutating the caller。在深入讨论之前,请回想一下我们之前说过的方法参数范围在方法定义级别,并且在方法定义之外不可用。例如:

def some_method(number)number = 7 # this is implicitly returned by the method
enda = 5
some_method(a)
puts a

在上面的代码中,我们传入 a 了 some_method 方法。在 中 some_method, 的值 a 被分配给局部变量 number,其作用域在方法定义级别。number 被重新赋值为 “7”。这是否影响了 a 的价值?答案是否定的,因为 number 范围在方法定义级别并且 a 的值未更改。因此,我们证明了方法定义不能永久修改传递给它们的参数。

当然,这个规则有一个例外。例外是当我们对改变 caller 的参数执行某些操作时,我们实际上可以永久更改方法定义范围之外的变量。

假设我们有一个 a 存储数组的局部变量。我们稍后也会更深入地介绍数组,但现在只需记住我们之前将数组解释为有序列表。在名为 mutate.rb 的文件中键入以下代码并运行它以查看结果。

我们在 puts 这里使用 p 代替。这两个非常相似,与 Ruby 打印输出的方式只有很小的不同。你可以同时尝试两种方式,看看我们为什么选择使用 p.

a = [1, 2, 3]# 永久修改其参数的方法定义的示例
def mutate(array)array.pop
endp "Before mutate method: #{a}"
mutate(a)
p "After mutate method: #{a}"

注意到每个打印输出之间的区别了吗?我们 a 通过将它传递给 mutate 方法来永久修改局部变量,即使 a 它超出了方法定义的范围。这是因为该 pop 方法会改变调用者。

让我们将其与不改变调用者但仍返回相同值的方法定义进行对比。

a = [1, 2, 3]# Example of a method definition that does not mutate the caller
def no_mutate(array)array.last
endp "Before no_mutate method: #{a}"
no_mutate(a)
p "After no_mutate method: #{a}"

你会注意到在方法调用之前和之后我们有相同的输出,所以我们知道它 a 没有以任何方式修改。这是因为该 last 方法不会改变调用者。

你怎么知道哪些方法会改变调用者,哪些不会?不幸的是,你必须通过查看文档或重复来记住它。

如果你有使用其他语言编程的经验,并且想知道 Ruby 是按值传递还是按引用传递语言,那么你可能会对答案感到失望。在某种程度上,Ruby 两者兼而有之!

put vs return

现在,你知道的方法是什么,它是如何工作的,我们可以讨论的区别 puts 和 return。你还没有真正了解过 return,那是因为在 Ruby 中,每个方法都返回执行的最后一行的计算结果。

让我们使用我们的 mutate.rb 文件来演示这一点。

a = [1, 2, 3]def mutate(array)array.pop
endp "Before mutate method: #{a}"
p mutate(a)
p "After mutate method: #{a}"我们使用该 p 方法打印出该 mutate 方法返回的任何值。我们的输出如下所示:"Before mutate method: [1, 2, 3]"
3
"After mutate method: [1, 2]"

这是发生了什么:

我们 a 按照最初定义的方式打印出来。
我们打印出 mutate 方法返回的值。
我们打印出 amutate 方法之后的值。

第二行,它返回一个 “3”,可能会让你有点困惑。发生的事情是该方法将结果 array.pop 返回到调用它的位置。pop 是 Array 类中的一个方法,用于删除数组的最后一个元素并返回它。

在我们总结之前,让我们先看看 return 它本身,以便我们能够完全理解它。让我们创建一个名为 demo 的文件 return.rb。请记住输入这些示例并创建文件。

def add_three(number)number + 3
endreturned_value = add_three(4)
puts returned_value

在这里,我们将 add_three 方法调用的返回值保存在一个名为 的变量中 returned_value。然后我们打印 returned_value 到输出,看看里面有什么。你的输出应该打印,7 因为这是方法调用返回的内容。

Ruby 方法总是返回表达式最后一行的计算结果,除非在它之前显式返回。如果你想明确返回一个值,你可以使用 return 关键字。

def add_three(number)return number + 3
endreturned_value = add_three(4)
puts returned_value

你的输出应该还是一样的,对吧?如果我们再次改变它会发生什么?如果我们运行下面的代码,屏幕上会打印什么?

def add_three(number)return number + 3number + 4
endreturned_value = add_three(4)
puts returned_value

上面的程序应该仍然输出 7,你告诉它返回的数字。

当你将 a 放在 return 和 add_three 方法定义的中间时,它只返回 number + 3 的计算结果,即 7,而不执行下一行。

你希望从本节中获得的主要观点之一是,从方法返回某些内容时不需要保留字 return。这是 Ruby 语言的一个特性。例如,考虑这个方法定义:

def just_assignment(number)foo = number + 3
end

just_assignment(2) 的值将是 5,因为赋值表达式的计算结果为 5,因此这就是返回的值。

那关于涵盖方法。你对 Ruby 的使用 越来越聪明,越来越自信。我们有一种很好的感觉,你可能也开始玩得很开心了。继续前进!它只会从这里变得更好。

链式方法

因为我们确信每个方法调用都会返回一些东西,所以我们可以将方法链接在一起,这使我们能够编写极具表现力和简洁的代码。

假设我们创建以下方法定义:

def add_three(n)n + 3
end

上面的方法将返回——不是打印出来,而是返回——传入的值增加了 3。我们可以这样使用它:

add_three(5)        # returns 8

由于 add_three 方法调用返回一个值,因此我们可以继续对返回值调用方法。

add_three(5).times { puts ‘this should print 8 times’}

这意味着我们 times 在 8 的返回值上调用该方法 add_three(5)。运行上面的代码 irb,你会得到:

this should print 8 times
this should print 8 times
this should print 8 times
this should print 8 times
this should print 8 times
this should print 8 times
this should print 8 times
this should print 8 times
=> 8

注意最后一行。这意味着整个表达式 add_three(5).times { puts ‘this should print 8 times’}返回 8,这意味着如果我们愿意,我们可以保持链接方法调用!

在 Ruby 中,经常会看到方法链接在一起形成优雅的代码。例如:

"hi there".length.to_s      # returns "8" - a String

这是因为 Stringlength 方法返回一个整数,我们可以调用 to_s 整数将它们转换为字符串。

好的,回到我们最初的 add_three 方法定义。让我们做一个小修改:

def add_three(n)puts n + 3
end

请注意,我们现在使用的 puts 是输出递增的值,而不是隐式返回它。以下是否有效:

add_three(5).times { puts "will this work?" }
``````ruby
如果我们运行代码,我们会得到这个错误:NoMethodError: undefined method `times' for nil:NilClass看起来像沿着这条线的某个地方,我们得到了 a,nil 不知道如何响应 times 方法调用。让我们一步一步来,然后运行 add_three(5)。输出是:
```ruby
8
=> nil

请注意,现在它按预期打印出递增的值,但返回值现在是 nil。puts 的结果是 return nil,因为 puts n + 3 是方法定义中的最后一个表达式,nil 现在由 add_three 方法调用返回。我们现在不能再使用 add_three 来保持链接方法,因为它返回 nil。

这是将方法链接在一起的一个非常重要的方面:如果链上的任何地方 nil 抛出异常或异常,则整个链接调用将中断。如果我们希望该 add_three 方法打印出递增的值并返回它,那么我们必须进行以下修复:

def add_three(n)new_value = n + 3puts new_valuenew_value
end

我们也可以使用 return new_value,但由于 new_value 是方法定义中的最后一个表达式,它被隐式返回。

方法调用作为参数

到目前为止,我们已经熟悉了方法的调用方式。让我们举一些简单的例子来回顾一下这个概念。我们将定义 add 和 subtract 方法并调用它们:

def add(a, b)a + b
enddef subtract(a, b)a - b
end

我们定义了两个方法 add,subtract 它们接受参数 a 和 b。我们假设两者都是整数值。回想一下,Ruby 隐式返回方法的最后一行;因为这里的两个方法定义都只包含一行,所以我们让 Ruby 通过使用隐式返回来发挥它的魔力。请注意,我们也可以使用显式返回来更具体。

现在让我们通过传递整数值来调用这些方法:

add(20, 45)
=> 65
# returns 65subtract(80, 10)
=> 70
# returns 70

不太明显的是,Ruby 实际上允许我们将方法调用作为参数传递给其他方法。换句话说,我们是说我们可以将 add(20, 45) 和 subtract(80, 10) 作为参数传递给另一个方法。

请记住,这些方法调用返回整数值,这允许我们执行此类操作。换句话说,返回的值是作为参数传递的。我们将通过定义一个 multiply 方法来说明:

def multiply(num1, num2)num1 * num2
end

现在,让我们将 add(20, 45) 和 subtract(80, 10) 作为参数传递给 multiply:

def multiply(num1, num2)num1 * num2
end

让我们看一个更复杂的例子:

add(subtract(80, 10), multiply(subtract(20, 6), add(30, 5)))
=> 560

让我们分解一下这是做什么的:

首先,我们传递 add 两个参数:subtract(80, 10) 和 multiply(subtract(20, 6), add(30, 5))。
第一个参数,subtract 方法调用,返回 70。
第二个参数,multiply 方法调用,还有两个参数:subtract(20, 6) 和 add(30, 5)。

在这里,subtract(20, 6) 返回 14 并 add(30, 5) 返回 35 因此方法调用变为 multiply(14, 35)。评估 multiply(14, 35) 现在返回 490。
最后,将这两个方法调用的返回值放在一起,我们 add(70, 490) 最终将返回 560.

使用嵌套方法调用时要注意的一件非常重要的事情是使用括号来防止任何类型的混淆。

我们已经看到方法调用总是返回一个值,我们可以根据返回值将该方法调用作为参数传递给另一个方法调用。因此,了解我们定义的方法返回的内容至关重要,因为归根结底,这实际上是作为参数传递给其他方法调用的内容。

调用栈

所有程序员都需要理解的方法的一个重要方面是调用堆栈的概念,或者更随意地,堆栈的概念。

调用堆栈可帮助 Ruby 跟踪正在执行的方法以及返回时应在何处恢复执行。要做到这一点,它就像一叠书:如果你有一叠书,你可以在最上面放一本新书或从书叠中取出最上面的书。以几乎相同的方式,调用堆栈将有关当前方法的信息放在堆栈顶部,然后在方法返回时删除该信息。

在 Ruby 中,方法并不是唯一使用调用堆栈的东西。Blocks、procs 和 lambdas 也使用调用堆栈;事实上,它们都使用与 Ruby 用于方法的相同调用堆栈。为简单起见,我们通常在讨论调用堆栈时只提及方法。但是,你应该始终记住,块、过程和 lambda 也是此过程的一部分。

假设我们有以下代码:

def firstputs "first method"
enddef secondfirstputs "second method"
endsecond
puts "main method"

当这个程序开始运行时,调用堆栈最初有一个项目——称为堆栈帧——代表程序的全局(顶级)部分。初始堆栈帧有时称为 main 方法。Ruby 使用这个框架来跟踪它当前正在处理的主程序的哪一部分。

当程序执行到达第 10 行的方法调用时,main 首先用当前程序位置更新堆栈帧。Ruby 稍后将使用此位置来确定在 second 完成运行后应继续执行的位置。

在当前堆栈帧中设置位置后,Ruby 为该 second 方法创建一个新堆栈帧并将其放在调用堆栈的顶部:我们说新帧被压入堆栈。我们的调用堆栈现在看起来像这样:

请注意,该 second 方法的框架现在堆叠在 main 框架的顶部。当 second 框架仍在堆栈上时,main 仍然卡在其下方,无法访问。同时,该 main 方法变为休眠状态,而该 second 方法变为活动状态。

该 second 方法调用第 first6 行的方法。该操作使 Ruby 更新 second 框架,以便 Ruby 知道稍后从何处恢复执行。然后它为该 first 方法创建一个新的堆栈帧并将其推送到调用堆栈。

一旦 first 方法开始执行,它就会调用该 puts 方法。所有 Ruby 方法,包括内置方法,如 puts,共享相同的调用堆栈。因此,我们需要记录我们当前的位置,然后将新帧推入堆栈:

有可能,puts 也有几个内部方法调用。但是,我们将忽略它们并假设 puts 它在没有任何其他方法调用的情况下完成了所有工作。相反,它只是将消息记录 first method 到控制台,然后立即返回。

当 puts 返回时,红宝石删除 - 啪啪 - 从调用堆栈的顶部框架。这就是 puts 本例中的框架。这会暴露前一个堆栈帧。Ruby 使用此框架来确定应从何处恢复执行。在这种情况下,执行会在第 2 行之后立即恢复。

最终,该 first 方法将返回。发生这种情况时,first 帧会从堆栈中弹出。这暴露了 的堆栈帧 second,然后告诉 Ruby 它应该在第 6 行恢复执行。

当 second 完成执行,为堆栈帧 second 被从调用堆栈中弹出,露出的堆栈帧 main。该 main 框架告诉 Ruby 在第 10 行恢复执行。

最终,该 main 方法不再需要运行代码。发生这种情况时,main 帧从堆栈中弹出,程序结束。

调用堆栈的大小有限,具体取决于 Ruby 实现。该大小通常足以容纳超过 10000 个堆栈条目。如果堆栈空间不足,你将看到 SystemStackError 异常。

如果你需要更直观的感受,请花 10 分钟观看 此视频。

请注意,该视频使用的是 JavaScript,而不是 Ruby。但是,视频的 JavaScript 部分非常基础,鉴于你目前的 Ruby 知识,应该不会太难理解。最重要的是,此时不要尝试学习 JavaScript。

视频中显示的 JavaScript 与你所了解的 Ruby 之间的主要区别在于,JavaScript 使用术语 “函数” 的方式与 Ruby 使用术语 “方法” 的方式大致相同。就我们的目的而言,它们代表相同的概念。在语法方面,JavaScript 使用 function 关键字来定义函数,而 Ruby 使用 def 关键字。

方法是 Ruby 编程的主要部分。了解什么是方法以及它执行的操作对于你作为 Ruby 程序员的开发至关重要。你将在大大小小的程序中不断使用它们。了解之间的差别 puts,并 return 会帮助你避免常见的错误,我们看到有很多初学者的斗争。最后,知道如何以及何时使用方法链将帮助你更好地阅读代码并让你编写更简洁的代码。但要注意那些零。

1 方法

方法是由对象定义的与该对象相关的操作。在 Ruby 中,对象的所有操作都被封装成方法。

方法的调用

Ruby 中方法的调用有很多种。

简单方法调用示例

对象。方法名 ( 参数 1,参数 2, … ,参数 n )

以对象开头,中间隔着句点 “.”,后面接着是方法名,方法名后面是一排并列的用 () 括起来的参数。不同的方法定义的参数个数和顺序也都不一样,调用方法时必须按照定义来指定参数。另外,调用方法时 () 是可以省略的。

上面的对象被称为接收者(receiver)。在面向对象的世界中,调用方法被称为 “向对象发送消息(message)”,调用的结果就是 “对象接收(receive)了消息” 也就是说,方法的调用就是把几个参数连同消息一起发送给对象的过程。

示例代码

name = 'peng'puts name.upcase
puts name.upcase() # 同上

带块的方法调用

对象 . 方法名 ( 参数 , …) do | 变量 1,变量 2, … | 块内容
end

示例代码

5.times do |i|puts " 第 #{i} 次循环。"
end

运算符形式的方法调用

Ruby 中有些方法看起来很像运算符。四则运算等二元运算符,-(负号)等一元运算符,指定数组、哈希的元素下标的 [] 等,实际上都是方法。

例如

a + b
# 等价于
a.+(b)

方法的分类

根据接收者种类的不同,Ruby 的方法可分为以下 3 类。

  1. 实例方法
  2. 类方法
  3. 函数式方法

实例方法

实例方法是最常用的方法。假设有一个对象(实例),那么以这个对象为接收者的方法就称为实例方法。

p "10, 20, 30, 40".split(",")
#=> ["10", "20", "30", "40"]p [1, 2, 3, 4].index(2)
#=> 1p 1000.to_s    #=> "1000"

在本例中,从上到下分别以字符串、数组、数值对象为接收者。

对象能使用的实例方法是由对象所属的类决定的。调用对象的实例方法后,程序就会执行对象所属的类预先定义好的处理。虽然相同名称的方法执行的处理大多都是一样的,但具体执行的内容则会根据对象类型的不同而存在差异。例如,几乎所有的对象都有 to_s 方法,这是一个把对象内容以字符串形式输出的方法。然而,虽然都是字符串形式,但在数值对象与时间对象的情况下,字符串形式以及字符串的创建方法都不一样。

类方法

接收者不是对象而是类本身的方法称为类方法。例如,我们在创建对象时就使用到了类方法。

示例代码

Array.new    # 创建新的数组
File.open("some_file")    # 创建新的文件对
Time.now    # 创建新的 Time 对象

函数式方法

没有接收者的方法,我们称为函数式方法。
虽说没有接收者,但并不表示该方法就真的没有可作为接收者的对象,只是在函数式方法的情况下,可以省略接收者而已。

示例代码

print "hello!"
# 在命令行输出字符串sleep(10)
# 在指定的时间内睡眠,终止程序

函数式方法的执行结果不会根据接收者的状态而发生变化。程序在执行 print 方法以及
sleep 方法时,并不需要知道接收者是谁。

反过来说,不需要接收者的方法就是函数式方法。

方法的定义

定义方法的一般语法如下所示:

def 方法名 ( 参数 1,参数 2, …) # 希望执行的处理
end

方法名可由英文字母、数字、下划线组成,但不能以数字开头。

方法定义示例

# 一般方法
def fun1p 'fun1'
end# 实例方法
class Userdef fun2p 'fun2'end
end# 类方法
class Userdef self.fun3p 'fun3'end
end

方法的返回值

我们可以用 return 语句指定方法的返回值。

定义带块的方法

def myloop while trueyieldend
endnum = 1myloop doputs "num is #{num}" num *= 2if num > 10breakend
end

参数个数不确定的方法

通过用 “* 变量名” 的形式来定义参数个数不确定的方法,就可以把所有参数封装为数组,供方法内部使用。

def foo(*args) args
endp foo(1, 2, 3)   #=> [1, 2, 3]

至少需要指定一个参数的方法可以像下面这样定义。

def meth(arg, *args)[arg, args]
endp meth(1)
p meth(1, 2, 3) #=> [1, [2, 3]]

关键字参数

在目前为止介绍过的方法定义中,都需要定义调用方法时的参数个数以及调用顺序。而使用
关键字参数,就可以将参数名与参数值成对地传给方法内部使用。

使用关键字参数定义方法的语法如下所示。

def 方法名(参数 1: 参数 1 的值 ,参数 2: 参数 2 的值 , …) # 希望执行的处理
end

方法的调用和定义在任何一本编程语言中都属于基础知识,并且每一门编程语言都有自己的风格。多学多练,是掌握编程语言的关键。

作为面向对象的脚本语言的 Ruby,还为我们提供了支持面向对象程序设计的功能。接下来, 我们首先会了解面向对象程序设计的共通概念——类,以及 Ruby 独有的功能——模块,然后再讨论面向对象程序设计的基本方法。

2 类是什么

类(class)是面向对象中一个重要的术语。类表示对象的种类。Ruby 中的对象一定都属于某个类。相同类的对象所使用的方法也相同。类就像是对象的雏形或设计图,决定了对象的行为。在生成新的对象时,一般会用到各个类的 new 方法。例如,使用 Array.new 方法可以生成新的数组对象。

创建类

创建类示例

class HelloWorlddef initialize(name)@name = nameenddef helloputs "Hello, #{@name}!"end
endpeng = HelloWorld.new("Peng")
peng.hello

class 语句在定义类时使用,以下是 class 语句的一般用法。

initialize 的方法比较特别。使用 new 方法生成新的对象时,initialize 方法会被调用,
同时 new 方法的参数也会被原封不动地传给 initialize 方法。因此初始化对象时需要的处理一般都写在这个方法中。

3 模块

模块是 Ruby 的特色功能之一。如果说类表现的是事物的实体(数据)及其行为(处理),那么模块表现的就只是事物的行为部分。

模块与类有以下两点不同。

  1. 模块不能拥有实例;
  2. 模块不能被继承。

模块示例

module M1def fun1p 'fun1'end
endmodule M2def fun2p 'fun2'enddef self.fun3p 'fun3'end
endclass Userinclude M1include M2
end

210 Ruby 方法、类和模块【Rails后端开发训练营】相关推荐

  1. Web后端开发训练营结课心得

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.SpringBoot简介 1.1 什么是SpringBoot 1.2 SpringBoot的主要特点 二.Spri ...

  2. python安装不了jieba_python安装jieba失败怎么办?_后端开发

    PHP中的=什么意思?_后端开发 PHP中的"="是一个基础的赋值运算符,意思是右侧赋值表达式为左侧运算数设置值.其他赋值运算符有:"+="."-=& ...

  3. Java后端开发工程师是否该转大数据开发?

    背景 看到一些java开发工程师,对java后端薪酬太悲观了.认为换去大数据领域就会高工资.觉得java后端没有前途.我从事java后端开发,对大数据领域工作有些了解,但不深入.本文描述一下我对jav ...

  4. 模块全解======ruby的类是单继承生物、所以出现了module、实现了多继承

    ruby的类是单继承生物.所以出现了module.实现了多继承. 注:模块.常量和类的命名都是以大写字母开头 . 模块引用:       1.如果引用的模块在同一个文件中,则直接使用模块操作      ...

  5. python 如何查看模块所有方法-Python查看模块(变量、函数、类)方法

    前面章节中,详细介绍了模块和包的创建和使用(严格来说,包本质上也是模块),有些读者可能有这样的疑问,即正确导入模块或者包之后,怎么知道该模块中具体包含哪些成员(变量.函数或者类)呢? 查看已导入模块( ...

  6. php7 匿名继承类_PHP7中的匿名类使用方法_后端开发

    PHP 微服务集群搭建 - Hyperf_后端开发 Hyperf 是基于 Swoole 4.4+ 实现的高性能.高灵活性的 PHP 协程框架,内置协程服务器及大量常用的组件,性能较传统基于 PHP-F ...

  7. 类和模块 类和原型 工厂方法 构造函数 constructor

    类和模块 每个js的对象都是属性的集合.相互之间没有联系. js也能定义对象的类,让每个对象都共享某些属性. 类的成员或者实例包含一些属性,用来存放或者定义他们的状态.有些属性定义了其行为,(行为或者 ...

  8. Java后端开发功能模块思路

    文章目录 前言 一.查找接口及参数信息 1.1 找访问路径 1.2 参数及返回结果信息 1.3 编写功能模块函数 二.代码设计思路 三.总结 前言 对于正在学习Java后端开发的同学来说,对于Java ...

  9. php类如何变为静态调用,PHP类中静态方法如何调用非静态方法?_后端开发

    php如何将字符串转成json_后端开发 php将字符串转成json的方法是:可以通过json_encode()函数来实现.json_encode()函数用于对变量进行JSON编码,该函数如果执行成功 ...

  10. ruby 变量类中范围_Ruby中的类

    ruby 变量类中范围 Ruby类 (Ruby Classes) In the actual world, we have many objects which belong to the same ...

最新文章

  1. openstack对比其他有什么优点
  2. TIOBE 8 月编程语言:C、Java 差距拉大,R 语言盛行
  3. golang-china
  4. Java记录-SpringMVC整合Echarts画地图加散点图
  5. 设计模式的理解:对23个设计模式的总结
  6. wxWidgets:文档/视图框架
  7. Quartz2D指定显示范围
  8. 微软MCITP系列课程(八)文件服务器及磁盘配额
  9. STM32的串口DMA收发以及双缓冲区的实现
  10. CCF CSP201909-1小明种苹果
  11. 从网络营销辞职转行软件测试,100天的心酸拿到9K,过程都是自己在苦撑,只因我...
  12. 计算机组成原理 确定片选逻辑,唐朔飞 计算机组成原理习题答案.ppt
  13. DirectX截图黑屏的解决办法
  14. 科技爱好者周刊:第 83 期
  15. 如何科学地评价妹子身材?三围符合黄金比例是审美标准?你错了!
  16. IT业狼多肉少?程序员的绝地求生,谁能给他们一把“98K”?
  17. win10右键菜单发送到的选项为空怎么解决
  18. 值得你收藏的几个实用识别图片文字软件都在这
  19. 神武服务器维护打副本,《神武4》电脑版:零氪也能玩转新服 注重细节能挣不少神武币...
  20. 论文阅读:GMAN: A Graph Multi-Attention Network for Traffic Prediction

热门文章

  1. java葫芦娃喜羊羊格斗_继明日之后看葫芦娃和奥特曼,玩家也能在绝地求生中看喜羊羊了...
  2. 用poi 给word文档添加水印
  3. 侯捷 C++ 课程系列视频 | 侯捷 STL 视频
  4. python人脸识别实验报告总结_人脸识别实验报告.doc
  5. source insight中文乱码
  6. 2019产品数据管理(PDM)技术说明
  7. Quick MTF,镜头图像质量测试应用程序
  8. php正则表达式在线测试工具,在线测试正则表达式工具:适合asp.net vb.net cs.net等Web或者Windows程序,便于你快速编写正确正则表达式,提供正则表达式模板供参考。...
  9. 推荐几款牛逼Chrome网页翻译插件,功能强大内容惊艳,务必低调使用
  10. 如何编辑运行HTML网页文件(HTML编辑工具使用介绍)