提交 faa03c52 编写于 作者: W wizardforcel

2020-03-18 10:42:58

上级 b22e0d58
## 捐
为了跟上我的工作并定期更新书籍,请考虑捐赠。 您可以在此处通过[PayPal]向我捐款 [https://www.paypal.me/mindaslab](https://www.paypal.me/mindaslab)
\ No newline at end of file
为了跟上我的工作并定期更新书籍,请考虑捐赠。 你可以在此处通过[PayPal]向我捐款 [https://www.paypal.me/mindaslab](https://www.paypal.me/mindaslab)
\ No newline at end of file
## 前言
自从我开始写《我爱红宝石》以来已有很长时间了。 我首先将这本书投影为玩具编程书,但现在不再如此,这本书已经发展成为一种严肃的东西。 有可能对认真的 Ruby 的人来说是一本书,因此这本书正在发生巨大的变化。 这本书完全用 Asciidoc 编写。 从上到下的证明都是正确的。 它的所有示例都适用于 Ruby 2.5,最后这本书在网上,epub,pdf 和印刷版中出现。 希望您喜欢学习 Ruby。
\ No newline at end of file
自从我开始写《我爱红宝石》以来已有很长时间了。 我首先将这本书投影为玩具编程书,但现在不再如此,这本书已经发展成为一种严肃的东西。 有可能对认真的 Ruby 的人来说是一本书,因此这本书正在发生巨大的变化。 这本书完全用 Asciidoc 编写。 从上到下的证明都是正确的。 它的所有示例都适用于 Ruby 2.5,最后这本书在网上,epub,pdf 和印刷版中出现。 希望你喜欢学习 Ruby。
\ No newline at end of file
......@@ -4,4 +4,4 @@ Ruby 是一种易于学习的编程语言,它是由日本的 Matz <sup clas
当我开始用 Ruby 编程时,我感到很兴奋。 我的第一个应用程序是为我妈妈(一位老师)设计的学生排名软件。 我仅用 32 行就能编写基于控制台的应用程序!!! 这让我睁开了眼睛,让我意识到了 Ruby 的强大功能。 该语言简单,易学且几乎完美。 目前,我是一名专业的 Ruby on Rails 程序员。
这本书是为 GNU / Linux(Debian 发行版)用户编写的,因为我认为 GNU / Linux 将在不久的将来征服程序员的桌面。 几乎所有拥有基于 Debian GNU / Linux 发行版的人都应该在尝试使用本书学习 Ruby 时感到宾至如归。 如果您使用的是 Solaris,OSX 或 Windows 等其他操作系统,请联系您的操作系统帮助渠道,以了解如何安装或开始使用 Ruby。 您也可以访问 [http://ruby-lang.org](http://ruby-lang.org) 了解 Ruby 入门。
\ No newline at end of file
这本书是为 GNU / Linux(Debian 发行版)用户编写的,因为我认为 GNU / Linux 将在不久的将来征服程序员的桌面。 几乎所有拥有基于 Debian GNU / Linux 发行版的人都应该在尝试使用本书学习 Ruby 时感到宾至如归。 如果你使用的是 Solaris,OSX 或 Windows 等其他操作系统,请联系你的操作系统帮助渠道,以了解如何安装或开始使用 Ruby。 你也可以访问 [http://ruby-lang.org](http://ruby-lang.org) 了解 Ruby 入门。
\ No newline at end of file
## 取得这本书
可以在此处 [https://i-love-ruby.gitlab.io/](https://i-love-ruby.gitlab.io/) 获得此书,并在 [https://gitlab.com/i-获得完整的书和源代码。 love-ruby / i-love-ruby.gitlab.io](https://gitlab.com/i-love-ruby/i-love-ruby.gitlab.io)
可以在此处 [https://i-love-ruby.gitlab.io/](https://i-love-ruby.gitlab.io/) 获得此书,并在 [https://gitlab.com/i-获得完整的书和源代码。 love-ruby / i-love-ruby.gitlab.io](https://gitlab.com/i-love-ruby/i-love-ruby.gitlab.io)
可以从此处 [https://i-love-ruby.gitlab.io/print.pdf](https://i-love-ruby.gitlab.io/print.pdf) 获得 PDF 版本。 可以在此处 [https://i-love-ruby.gitlab.io/epub.epub](https://i-love-ruby.gitlab.io/epub.epub) 找到 Epub 版本。
### 在亚马逊上
如果您想要这本书的印刷版,可以在 [https://www.amazon.com/dp/1796378429/](https://www.amazon.com/dp/1796378429/) 中找到。 亚马逊也为您提供了 ePub 版本,但需要付费。 我正在努力制作免费的 ePub 版本。 让我们来看看。
如果你想要这本书的印刷版,可以在 [https://www.amazon.com/dp/1796378429/](https://www.amazon.com/dp/1796378429/) 中找到。 亚马逊也为你提供了 ePub 版本,但需要付费。 我正在努力制作免费的 ePub 版本。 让我们来看看。
### 联系作者
您可以通过 [mindaslab@protonmail.com](mailto:mindaslab@protonmail.com) 或通过电话+91 8428050777 或通过 Twitter @karthik_ak 与 Karthikeyan A K 联系。 我希望收到阅读我的书的人的来信,所以如果您愿意,请写信给我。
\ No newline at end of file
你可以通过 [mindaslab@protonmail.com](mailto:mindaslab@protonmail.com) 或通过电话+91 8428050777 或通过 Twitter @karthik_ak 与 Karthikeyan A K 联系。 我希望收到阅读我的书的人的来信,所以如果你愿意,请写信给我。
\ No newline at end of file
## 先决条件
本书为您提供了足够的知识,可以从头开始学习 Ruby。 但是,如果您已经知道或拥有这些东西,那将是很好的。 首先是一台 GNU / Linux 计算机。 我建议使用 Ubuntu [https://ubuntu.com](https://ubuntu.com) 计算机。 该操作系统正在成为每个优秀程序员的操作系统。 您要做的第二件事是培养 GNU / Linux 的知识,您可以阅读 [https://linuxjourney.com](https://linuxjourney.com) 上的教程以获取知识。 一旦掌握了这些知识,您将可以更好地学习 Ruby。
\ No newline at end of file
本书为你提供了足够的知识,可以从头开始学习 Ruby。 但是,如果你已经知道或拥有这些东西,那将是很好的。 首先是一台 GNU / Linux 计算机。 我建议使用 Ubuntu [https://ubuntu.com](https://ubuntu.com) 计算机。 该操作系统正在成为每个优秀程序员的操作系统。 你要做的第二件事是培养 GNU / Linux 的知识,你可以阅读 [https://linuxjourney.com](https://linuxjourney.com) 上的教程以获取知识。 一旦掌握了这些知识,你将可以更好地学习 Ruby。
\ No newline at end of file
......@@ -2,11 +2,11 @@
### 1.1。 在 Debian Flavor GNU / Linux 上安装 Ruby
您需要安装称为 RVM(红宝石版本管理器)的东西,它将管理多个 ruby 版本。 为什么? 这是因为 Ruby 的版本变化如此之快。在您使用 1.8 之前,现在是 1.9,不久之后 Ruby 2 就会问世。 除了仅使用 Ruby 之外,您还可以将其用于其他东西,例如带有 Sinatra 和 Ruby on RailsTM 软件包的 Web 开发。 您可能需要从一个版本更改为另一个版本,而不必一次又一次卸载并重新安装 ruby。 RVM 为您管理。 通过简单的命令,我们可以轻松地在 Ruby 版本之间切换。
你需要安装称为 RVM(红宝石版本管理器)的东西,它将管理多个 ruby 版本。 为什么? 这是因为 Ruby 的版本变化如此之快。在你使用 1.8 之前,现在是 1.9,不久之后 Ruby 2 就会问世。 除了仅使用 Ruby 之外,你还可以将其用于其他东西,例如带有 Sinatra 和 Ruby on RailsTM 软件包的 Web 开发。 你可能需要从一个版本更改为另一个版本,而不必一次又一次卸载并重新安装 ruby。 RVM 为你管理。 通过简单的命令,我们可以轻松地在 Ruby 版本之间切换。
**安装 RVM:**
OK,要安装 RVM,需要具备 curl(可以下载内容的程序)。 要卷曲,只需键入
OK,要安装 RVM,需要具备 curl(可以下载内容的程序)。 要卷曲,只需键入
```rb
$ sudo apt-get install curl
......@@ -36,7 +36,7 @@ $ source ~/.bashrc
$ rvm install ruby
```
完成此操作后,可能需要重新启动终端。 打开终端并输入以下内容:
完成此操作后,可能需要重新启动终端。 打开终端并输入以下内容:
```rb
$ ruby -v
......@@ -52,7 +52,7 @@ ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux]
### 1.2。 安装 IDE
需要一个良好的 IDE(集成开发环境)来开始使用 Ruby。 我建议使用简单轻便的 IDE Geany1。 要在 Ubuntu 中安装 IDE,只需键入(不带$):
需要一个良好的 IDE(集成开发环境)来开始使用 Ruby。 我建议使用简单轻便的 IDE Geany1。 要在 Ubuntu 中安装 IDE,只需键入(不带$):
```rb
$ sudo apt-get install geany
......
## 2.在线资源
Ruby 拥有一个出色的在线黑客社区,他们随时准备帮助几乎对 Ruby 有任何疑问的任何人。 他们喜欢编程语言,希望其他人喜欢和体验它。 Ruby 是一种很棒的编程语言,它将使您的内心深处受益。 一旦您了解了它并开始与其他黑客互动,您自然就会倾向于帮助他人。 因此,请访问本节推荐的网站。 它们可能对您很有用。
Ruby 拥有一个出色的在线黑客社区,他们随时准备帮助几乎对 Ruby 有任何疑问的任何人。 他们喜欢编程语言,希望其他人喜欢和体验它。 Ruby 是一种很棒的编程语言,它将使你的内心深处受益。 一旦你了解了它并开始与其他黑客互动,你自然就会倾向于帮助他人。 因此,请访问本节推荐的网站。 它们可能对你很有用。
### 2.1。 Ruby 网站
网址: [http://ruby-lang.org](http://ruby-lang.org)
Ruby 网站是从 Ruby 开始的好地方。 它为您提供了在操作系统上安装 Ruby 的安装程序。 它具有很酷的链接,例如“尝试 Ruby! 在您的浏览器中”,这使您可以直接从 Web 浏览器中试用 Ruby,并且一个名为“ Ruby in Twenty Minutes”的链接将教您 Ruby 编程的基础知识。 Ruby 是一种简单的语言,您只需要 20 分钟就可以掌握它! 相信我,这是真的!
Ruby 网站是从 Ruby 开始的好地方。 它为你提供了在操作系统上安装 Ruby 的安装程序。 它具有很酷的链接,例如“尝试 Ruby! 在你的浏览器中”,这使你可以直接从 Web 浏览器中试用 Ruby,并且一个名为“ Ruby in Twenty Minutes”的链接将教你 Ruby 编程的基础知识。 Ruby 是一种简单的语言,你只需要 20 分钟就可以掌握它! 相信我,这是真的!
### 2.2。 Reddit
Reddit 有一个非常活跃的 Ruby 社区。 您可以在 [https://www.reddit.com/r/ruby/](https://www.reddit.com/r/ruby/) 中找到它。 关于 reddit 的伟大之处在于,故事被其他用户之以鼻,什么才是最好的泡沫。 如果您正在寻找 Ruby 或其他任何技术主题的真正趋势,我发现 reddit 是最好的。
Reddit 有一个非常活跃的 Ruby 社区。 你可以在 [https://www.reddit.com/r/ruby/](https://www.reddit.com/r/ruby/) 中找到它。 关于 reddit 的伟大之处在于,故事被其他用户之以鼻,什么才是最好的泡沫。 如果你正在寻找 Ruby 或其他任何技术主题的真正趋势,我发现 reddit 是最好的。
### 2.3。 红宝石流
Ruby flow 是一个网站,我可以使用它随意阅读 Ruby 社区中发生的事情。 这是一个非常干净的网站,Rubyist 可以在其​​中发布他们认为其他 Rubyists 必须了解的关于 Ruby 的信息。 可以在此处访问它 [http://www.rubyflow.com/](http://www.rubyflow.com/)
Ruby flow 是一个网站,我可以使用它随意阅读 Ruby 社区中发生的事情。 这是一个非常干净的网站,Rubyist 可以在其​​中发布他们认为其他 Rubyists 必须了解的关于 Ruby 的信息。 可以在此处访问它 [http://www.rubyflow.com/](http://www.rubyflow.com/)
### 2.4。 推特
网址: [http://twitter.com](http://twitter.com)
Twitter 是一个社交网站。 那我为什么要放在地球上呢? 很多 Ruby 程序员都使用 twitter,这可能是因为 Twitter 最初是用 Ruby 编写的。 要获取有关“ Ruby 编程”的最新消息,请在搜索栏中键入它,然后按搜索。 您将获得有关 Ruby 语言的最新趋势主题。 尝试搜索诸如“ Ruby 语言”之类的等等。
\ No newline at end of file
Twitter 是一个社交网站。 那我为什么要放在地球上呢? 很多 Ruby 程序员都使用 twitter,这可能是因为 Twitter 最初是用 Ruby 编写的。 要获取有关“ Ruby 编程”的最新消息,请在搜索栏中键入它,然后按搜索。 你将获得有关 Ruby 语言的最新趋势主题。 尝试搜索诸如“ Ruby 语言”之类的等等。
\ No newline at end of file
此差异已折叠。
......@@ -2,7 +2,7 @@
### 4.1。 逻辑运算符
逻辑运算符使您可以确定天气是否正确。 例如,一个就是一个,那就是人类的想法,让我们看看计算机对此的想法。 发射您的 irb 并输入 1 等于 1,如图所示
逻辑运算符使你可以确定天气是否正确。 例如,一个就是一个,那就是人类的想法,让我们看看计算机对此的想法。 发射你的 irb 并输入 1 等于 1,如图所示
```rb
>> 1 == 1
......@@ -94,7 +94,7 @@
=> false
```
也可以尝试使用数字
也可以尝试使用数字
<colgroup><col style="width: 50%;"> <col style="width: 50%;"></colgroup>
| 操作员 | 含义 |
......@@ -105,7 +105,7 @@
### 4.2。 true!=“ true”
在逻辑运算符部分,您可能会看到 irb 提供`true``false`作为输出。 您不要与`“true”``“false”`混淆。 `true``false`是逻辑值,而`“true”``“false”``String`
在逻辑运算符部分,你可能会看到 irb 提供`true``false`作为输出。 你不要与`“true”``“false”`混淆。 `true``false`是逻辑值,而`“true”``“false”``String`
### 4.3。 ===
......@@ -125,7 +125,7 @@
=> false
```
在上面的示例中,由于`7`绝对不是`String`,因此它显然返回 false,这就是可能会想到的;)
在上面的示例中,由于`7`绝对不是`String`,因此它显然返回 false,这就是可能会想到的;)
但是有些奇怪,请看下面的例子
......@@ -149,7 +149,7 @@ puts "#{name} is genius" if name == "Zigor"
puts "#{name} is idiot" if name != "Zigor"
```
如果输入的名称不是 Zigor,结果将会是这样
如果输入的名称不是 Zigor,结果将会是这样
```rb
Whats your name?
......@@ -163,7 +163,7 @@ Karthik is idiot
puts "#{name} is genius" if name == "Zigor"
```
该程序在名为`name`的变量中获取的名字。 现在,它检查上面代码中名称是否为 Zigor(在关键字`if`的右侧),如果是,则执行与之关联的语句(即关键字`if`的左侧的语句) ),在这种情况下,它会打印出特定的名称是 genius。 然后归结为下一条语句
该程序在名为`name`的变量中获取的名字。 现在,它检查上面代码中名称是否为 Zigor(在关键字`if`的右侧),如果是,则执行与之关联的语句(即关键字`if`的左侧的语句) ),在这种情况下,它会打印出特定的名称是 genius。 然后归结为下一条语句
```rb
puts "#{name} is idiot" if name != "Zigor"
......@@ -219,7 +219,7 @@ if <condition>
end
```
在上面,可以在`if … end`块中放入许多需要执行的代码。
在上面,可以在`if … end`块中放入许多需要执行的代码。
### 4.6。 埃尔斯夫
......@@ -306,7 +306,7 @@ Enter your age:16
"You are a minor"
```
程序会询问您的年龄,如果年龄不大于 18,则表示您是未成年人。也就是说,除非您的年龄大于或等于 18(如在此情况下所示),否则您将是未成年人`unless age &gt;= 18``p`是看跌期权 &lt;sup class="footnote"&gt;[ [13](#_footnotedef_13 "View footnote.") ]&lt;/sup&gt; 的简称。 如果编写`puts “something”`,则红宝石解释程序将打印`something`。 如果您使用`p ”something”`,则红宝石解释器将打印`”something”`(这与这些引号一起使用)。
程序会询问你的年龄,如果年龄不大于 18,则表示你是未成年人。也就是说,除非你的年龄大于或等于 18(如在此情况下所示),否则你将是未成年人`unless age &gt;= 18``p`是看跌期权 &lt;sup class="footnote"&gt;[ [13](#_footnotedef_13 "View footnote.") ]&lt;/sup&gt; 的简称。 如果编写`puts “something”`,则红宝石解释程序将打印`something`。 如果你使用`p ”something”`,则红宝石解释器将打印`”something”`(这与这些引号一起使用)。
如果我们想在`unless`块下放置多行代码,可以使用`unless …​. end`块,如下所示
......@@ -339,7 +339,7 @@ Enter your age:37
"You are a grown up"
```
好的,这是它的工作原理,可以确定年龄,将其转换为`age = gets.to_i`中的整数,并将其存储在名为`age`的变量中。 专注于这段代码:
好的,这是它的工作原理,可以确定年龄,将其转换为`age = gets.to_i`中的整数,并将其存储在名为`age`的变量中。 专注于这段代码:
```rb
unless age >= 18
......@@ -369,11 +369,11 @@ Enter your age:23
"You can enter Armed forces"
```
我认为可以自行解释该程序。 如果没有其他联系方式,除非我很懒,否则我会写一个解释。
我认为可以自行解释该程序。 如果没有其他联系方式,除非我很懒,否则我会写一个解释。
### 4.10。 情况何时
假设要编写一个程序,该程序对于确定的输入具有确定的输出,则可以在以下情况下使用这种情况。 假设我们要编写一个拼写为 1 到 5 的程序,我们可以按照 code / case_when.rb [case_when.rb]中所示的方法进行操作,在文本编辑器中键入该程序并执行。
假设要编写一个程序,该程序对于确定的输入具有确定的输出,则可以在以下情况下使用这种情况。 假设我们要编写一个拼写为 1 到 5 的程序,我们可以按照 code / case_when.rb [case_when.rb]中所示的方法进行操作,在文本编辑器中键入该程序并执行。
```rb
# case_when.rb
......@@ -496,7 +496,7 @@ Output
7 is odd
```
注意,在上面的程序中,我们为变量`num`分配了值 7,接下来,我们将`num`放入`case`语句中。 当数字为 1、3、5、7 和 9 时,我们需要打印其奇数,因此我们要做的只是对个案进行分组。 如果满意,则必须将其打印为`odd`,如果按照下面的代码所示放置,就足够了
注意,在上面的程序中,我们为变量`num`分配了值 7,接下来,我们将`num`放入`case`语句中。 当数字为 1、3、5、7 和 9 时,我们需要打印其奇数,因此我们要做的只是对个案进行分组。 如果满意,则必须将其打印为`odd`,如果按照下面的代码所示放置,就足够了
```rb
case num
......@@ -529,7 +529,7 @@ end
=> String
```
在第一条语句中,我们查询了`1`的类/对象类型,并说其类型为`Integer`。 当被问及`“Zigor”`的类别时,它说`String`。 在 Ruby 中,可以使用此函数来了解所使用的类型变量。 它是一个非常强大的功能。
在第一条语句中,我们查询了`1`的类/对象类型,并说其类型为`Integer`。 当被问及`“Zigor”`的类别时,它说`String`。 在 Ruby 中,可以使用此函数来了解所使用的类型变量。 它是一个非常强大的功能。
现在看看下面的程序
......@@ -605,11 +605,11 @@ Output
76 is even
```
要理解以上示例,必须先阅读 Proc,Lambda 和 Blocks。 观看代码`when → (n) { n % 2 == 0 }`,在其中将一个 lambda 传递给`when`,当调用该代码时,它将为`n`的值 76 或任何偶数返回`true`,如果`n`为奇数则返回`false` 。 因此,与以前的奇偶程序不同,它适用于从零到无限的所有自然数。
要理解以上示例,必须先阅读 Proc,Lambda 和 Blocks。 观看代码`when → (n) { n % 2 == 0 }`,在其中将一个 lambda 传递给`when`,当调用该代码时,它将为`n`的值 76 或任何偶数返回`true`,如果`n`为奇数则返回`false` 。 因此,与以前的奇偶程序不同,它适用于从零到无限的所有自然数。
### 4.15。 case 和 matcher 类的情况
要了解下面的程序,需要阅读===并检查案例类型时的大小写。 在下面输入程序并执行
要了解下面的程序,需要阅读===并检查案例类型时的大小写。 在下面输入程序并执行
```rb
# case_when_matcher_classes.rb
......@@ -657,7 +657,7 @@ end
在这里我们定义`self.===`,在其中接受一个参数字符串,在这里传递给`case``name`被复制到`string`,并检查`string``downcase`是否等于`“zigor”``string.downcase == "zigor"`中,如果是,则返回`true`,否则返回`false`。 如果`true`被执行,当 when Zigor 块中的代码被执行时,我们得到输出`Nice to meet you Zigor!!!`。 将名称更改为其他值,然后看看会发生什么。
如果您现在不了解此章节,请不要担心。 在完成本书的复习之后,您可能会更好地理解它。
如果你现在不了解此章节,请不要担心。 在完成本书的复习之后,你可能会更好地理解它。
### 4.16。 ? :
......@@ -683,7 +683,7 @@ p "max = "+max.to_s
<evaluate something > ? <if true take this thing> : <if false take this thing>
```
在问号之前给出一个表达式。 该表达式必须返回`true``false`。 如果表达式返回 true,则`it`返回`?``:`之间的内容;如果`false`,则返回`:`之后的内容。
在问号之前给出一个表达式。 该表达式必须返回`true``false`。 如果表达式返回 true,则`it`返回`?``:`之间的内容;如果`false`,则返回`:`之后的内容。
在表达中
......@@ -701,7 +701,7 @@ max = 3 > 5 ? 3 : 5
### 4.17。 将逻辑语句分配给变量
不管是否注意到了天气,在前面的示例 [max_of_nums.rb](code/max_of_nums.rb) 中,我们使用了这样的语句
不管是否注意到了天气,在前面的示例 [max_of_nums.rb](code/max_of_nums.rb) 中,我们使用了这样的语句
```rb
max = a > b ? a : b
......@@ -763,9 +763,9 @@ p "max = "+max.to_s
"max = 5"
```
那么要推断什么呢? 规则是这样的,如果在一个块中给出许多语句并将其分配给一个变量,则最后一条语句的输出将被返回并将被放入变量 &lt;sup class="footnote"&gt;[ [15](#_footnotedef_15 "View footnote.") ]&lt;/sup&gt; (在这种情况下为最大值)。
那么要推断什么呢? 规则是这样的,如果在一个块中给出许多语句并将其分配给一个变量,则最后一条语句的输出将被返回并将被放入变量 &lt;sup class="footnote"&gt;[ [15](#_footnotedef_15 "View footnote.") ]&lt;/sup&gt; (在这种情况下为最大值)。
这是另一个程序, [case_when.rb](code/case_when.rb) 的分支,我想知道它现在如何工作
这是另一个程序, [case_when.rb](code/case_when.rb) 的分支,我想知道它现在如何工作
```rb
# case_when_2.rb
......
## 5.循环
有时可能需要执行一些重复性的任务,比如说我想编写一个火箭倒计时程序,我想创建一个自动为火箭倒数的机器人,当计数结束时会说“ Blast Off”,让我们写一个 看看
有时可能需要执行一些重复性的任务,比如说我想编写一个火箭倒计时程序,我想创建一个自动为火箭倒数的机器人,当计数结束时会说“ Blast Off”,让我们写一个 看看
```rb
# count_down.rb
......@@ -22,7 +22,7 @@ p 1
p "Blast Off!"
```
好吧,希望能理解上面的程序。 我想说明的是,`p``puts`的一种简短形式,不用写`puts`就能使用`p`并得到相同的结果 &lt;sup class="footnote"&gt;[ [16 [](#_footnotedef_16 "View footnote.") ]&lt;/sup&gt; 。 上面的程序在运行时显示以下内容
好吧,希望能理解上面的程序。 我想说明的是,`p``puts`的一种简短形式,不用写`puts`就能使用`p`并得到相同的结果 &lt;sup class="footnote"&gt;[ [16 [](#_footnotedef_16 "View footnote.") ]&lt;/sup&gt; 。 上面的程序在运行时显示以下内容
```rb
Hello, I am Zigor....
......@@ -44,7 +44,7 @@ I count down for rockets
### 5.1。 向下
的文本编辑器中,键入以下程序
的文本编辑器中,键入以下程序
```rb
# count_down_1.rb
......@@ -59,9 +59,9 @@ end
p "Blast Off!"
```
运行它,看看。 好了,的程序现在使用了更少的代码,但是却产生了相同的结果!
运行它,看看。 好了,的程序现在使用了更少的代码,但是却产生了相同的结果!
注意事情`10.downto 1`,该语句使 Zigor 从 10 倒数到 1,而在倒数的同时,您可以使用倒数值做一些事情,还可以在循环块中放入一些代码。 循环以`do`开始,并在遇到`end`命令时结束。 您输入的任何代码都应介于`do``block` &lt;sup class="footnote"&gt;[ [17](#_footnotedef_17 "View footnote.") ]&lt;/sup&gt; 之间
注意事情`10.downto 1`,该语句使 Zigor 从 10 倒数到 1,而在倒数的同时,你可以使用倒数值做一些事情,还可以在循环块中放入一些代码。 循环以`do`开始,并在遇到`end`命令时结束。 你输入的任何代码都应介于`do``block` &lt;sup class="footnote"&gt;[ [17](#_footnotedef_17 "View footnote.") ]&lt;/sup&gt; 之间
```rb
10.downto 1 do
......@@ -87,7 +87,7 @@ end
### 5.2。 次
times 是一个非常简单的循环,如果想让代码执行 N 次,则将代码放入其中。 现在让我们看看 Zigor 知道什么
times 是一个非常简单的循环,如果想让代码执行 N 次,则将代码放入其中。 现在让我们看看 Zigor 知道什么
```rb
# times.rb
......@@ -141,7 +141,7 @@ I am going to tell what I know
6\. I know something
```
为什么从零数到六而不是一七呢? 好吧,如果一切按您的意愿进行,那么就不需要像您和我这样的程序员了,所以不要打扰。 请注意,在这些程序中,我们使用`{``}`,而不是 do and end。 好吧,Ruby 鼓励使用不同的编程风格。
为什么从零数到六而不是一七呢? 好吧,如果一切按你的意愿进行,那么就不需要像你和我这样的程序员了,所以不要打扰。 请注意,在这些程序中,我们使用`{``}`,而不是 do and end。 好吧,Ruby 鼓励使用不同的编程风格。
### 5.3。 取决于
......@@ -298,7 +298,7 @@ end
**更新**
假设我们忘了在循环体中包含`i+=1`,在每次迭代结束时,`i`的值将始终保持为 1,而我将始终保持小于 10,因此循环将被执行无数次,并且 将打印无限的 1。 实际上,的程序将崩溃,并可能导致不良后果。 为了避免这种情况,我们必须包含更新声明。 在这里,我们放置了`i+=1`,它在每次迭代继续时将`i`的值增加一,这确保`i⇐10`在某个阶段变为`false`,因此循环停止执行 &lt;sup class="footnote"&gt;[ [19 [](#_footnotedef_19 "View footnote.") ]&lt;/sup&gt;
假设我们忘了在循环体中包含`i+=1`,在每次迭代结束时,`i`的值将始终保持为 1,而我将始终保持小于 10,因此循环将被执行无数次,并且 将打印无限的 1。 实际上,的程序将崩溃,并可能导致不良后果。 为了避免这种情况,我们必须包含更新声明。 在这里,我们放置了`i+=1`,它在每次迭代继续时将`i`的值增加一,这确保`i⇐10`在某个阶段变为`false`,因此循环停止执行 &lt;sup class="footnote"&gt;[ [19 [](#_footnotedef_19 "View footnote.") ]&lt;/sup&gt;
因此,我们看到,为了使循环以理想的方式工作,我们需要使这四个部分交响。
......@@ -315,7 +315,7 @@ until i>10 do
end
```
这就是将得到的结果
这就是将得到的结果
```rb
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
......@@ -325,7 +325,7 @@ end
### 5.7。 打破
假设想脱离循环,也就是停止执行循环,可以使用`break`命令。 下面给出一个例子。 在示例中,如果迭代变量`i`变为 6,我们将中断操作。因此,仅输出 1 到 5 范围内的数字。 当`i`变为 6 时,循环中断或终止
假设想脱离循环,也就是停止执行循环,可以使用`break`命令。 下面给出一个例子。 在示例中,如果迭代变量`i`变为 6,我们将中断操作。因此,仅输出 1 到 5 范围内的数字。 当`i`变为 6 时,循环中断或终止
```rb
#break.rb
......@@ -344,7 +344,7 @@ end
### 5.8。 下一个
`break`,退出循环并终止。 `next``break`有所不同,它不是中断循环,而是继续循环而不执行`next`之后发生的语句的信号。 这是一个供理解的示例
`break`,退出循环并终止。 `next``break`有所不同,它不是中断循环,而是继续循环而不执行`next`之后发生的语句的信号。 这是一个供理解的示例
```rb
# next.rb
......@@ -370,7 +370,7 @@ Output
9
```
如果注意到输出,则看到打印了从 0 到 9 的数字,但没有打印出 6。请注意 [next.rb](code/next.rb) 中的`next if num == 6`行,如果`num``6``next`被执行,换言之`do` `end`块之后的所有行均被跳过。 与`brake`不同,循环不会终止,而是仅跳过`next`之后的行,循环继续进行。
如果注意到输出,则看到打印了从 0 到 9 的数字,但没有打印出 6。请注意 [next.rb](code/next.rb) 中的`next if num == 6`行,如果`num``6``next`被执行,换言之`do` `end`块之后的所有行均被跳过。 与`brake`不同,循环不会终止,而是仅跳过`next`之后的行,循环继续进行。
### 5.9。 重做
......@@ -387,11 +387,11 @@ Output
end
```
运行它,希望可以自己解释;-)
运行它,希望可以自己解释;-)
### 5.10。 环
因此,到目前为止,我们已经看到了许多类型的循环,但是我省略了一个称为`loop`的基本循环。 为什么我忽略了它,因为使用 &lt;sup class="footnote"&gt;[ [21](#_footnotedef_21 "View footnote.") ]&lt;/sup&gt; 危险。 好吧,让我们看一个例子。 在下面键入程序并执行。 请注意,需要按 Ctrl + C 才能停止执行。 所以要小心一点
因此,到目前为止,我们已经看到了许多类型的循环,但是我省略了一个称为`loop`的基本循环。 为什么我忽略了它,因为使用 &lt;sup class="footnote"&gt;[ [21](#_footnotedef_21 "View footnote.") ]&lt;/sup&gt; 危险。 好吧,让我们看一个例子。 在下面键入程序并执行。 请注意,需要按 Ctrl + C 才能停止执行。 所以要小心一点
```rb
# loop.rb
......@@ -417,7 +417,7 @@ I Love Ruby
......
```
输出将继续打印`I Love Ruby`,直到按 Ctrl 和 C 键使输出断开为止。 基本是这样的:循环执行和结束之间的任何操作都将继续进行。
输出将继续打印`I Love Ruby`,直到按 Ctrl 和 C 键使输出断开为止。 基本是这样的:循环执行和结束之间的任何操作都将继续进行。
现在让我们说我们不希望这个循环永远持续运行。 让我们看看如何驯服它。 让我们打印一个可以打印 1 到 10 的程序。在下面键入该程序并运行。
......
## 6.数组
阵列可以视为机架。 您可以将任何东西 1 放在机架中,以类似的方式可以将任何东西放在阵列中。 一个机架包含许多架子或隔层。 如果您可以数数,则可以在每个隔间上放置数字,可以认为机架是用于存储某些东西的空间阵列。 每个隔间可以用数字标识,因此易于识别。 阵列是可供程序员使用的机架。 让我们看一个示例以了解更多信息。 在下面输入程序并执行
阵列可以视为机架。 你可以将任何东西 1 放在机架中,以类似的方式可以将任何东西放在阵列中。 一个机架包含许多架子或隔层。 如果你可以数数,则可以在每个隔间上放置数字,可以认为机架是用于存储某些东西的空间阵列。 每个隔间可以用数字标识,因此易于识别。 阵列是可供程序员使用的机架。 让我们看一个示例以了解更多信息。 在下面输入程序并执行
```rb
# array.rb
......@@ -15,7 +15,7 @@ my_array.each do |element|
end
```
这就是将获得输出的方式
这就是将获得输出的方式
```rb
Something
......@@ -31,7 +31,7 @@ my_array << 123
my_array << Time.now
```
我们将元素追加到数组。 在第一条语句中,我们附加字符串常量`“Something”`,在第二条语句中,我们附加整数`123`,在第三条语句中,我们附加当前时间。 如果猜对了,我们已经使用`&lt;&lt;`运算符将值附加到数组。
我们将元素追加到数组。 在第一条语句中,我们附加字符串常量`“Something”`,在第二条语句中,我们附加整数`123`,在第三条语句中,我们附加当前时间。 如果猜对了,我们已经使用`&lt;&lt;`运算符将值附加到数组。
到现在为止,我们已经创建了一个名为`my_array`的数组,并将其放入其中。 现在,我们必须查看所输入的内容。为此,我们使用`&lt;array_name&gt;.each`(每个数组名称点一个点)。 此方法提取数组的每个元素。 因此,对于 my_array,我们使用`my_array.each`
......@@ -174,7 +174,7 @@ ArgumentError: wrong number of arguments (3 for 2)
from :0
```
所见,它失败了! 不要那样使用。
所见,它失败了! 不要那样使用。
好的,现在让我们在`array`上进行一些尝试,首先要获取`array`中有多少个元素,我们可以使用`length`函数,如下所示:
......@@ -215,7 +215,7 @@ ArgumentError: wrong number of arguments (3 for 2)
我们看到数组大小减少了一个,最后一个元素 5 丢失了。
它不是只需要在`push`中给出固定值,而是可以将变量和 Ruby 表达式以及任何对象作为参数提供给 push。 可以在下面看到我们将 2 提升到 10 的幂到数组,最后将 1024 添加到数组。
它不是只需要在`push`中给出固定值,而是可以将变量和 Ruby 表达式以及任何对象作为参数提供给 push。 可以在下面看到我们将 2 提升到 10 的幂到数组,最后将 1024 添加到数组。
```rb
>> array.push 2**10
......@@ -238,7 +238,7 @@ ArgumentError: wrong number of arguments (3 for 2)
=> ["Something", 123]
```
所见,第三个元素被弹出,因此可以随机弹出。
所见,第三个元素被弹出,因此可以随机弹出。
我们可以一次将许多元素推入数组。 考虑下面的代码片段
......@@ -256,7 +256,7 @@ ArgumentError: wrong number of arguments (3 for 2)
=> [5, "Who am I?", 563.16]
```
所见,数组的大小减小了,现在只有两个元素。
所见,数组的大小减小了,现在只有两个元素。
```rb
>> array
......@@ -272,9 +272,9 @@ ArgumentError: wrong number of arguments (3 for 2)
=> ["Something", 123, "a new element", 64]
```
在上面看到的,我们使用`&lt;&lt;`运算符将字符串常量`“a new element”``64`附加到数组。
在上面看到的,我们使用`&lt;&lt;`运算符将字符串常量`“a new element”``64`附加到数组。
可以使用`max``min`函数在数组中找到最大值和最小值,如下所示:
可以使用`max``min`函数在数组中找到最大值和最小值,如下所示:
```rb
>> nums = [1, 2, 64, -17, 5 ,81]
......@@ -300,7 +300,7 @@ ArgumentError: wrong number of arguments (3 for 2)
### 6.3。 设定操作
对于那些了解集合论的人,您必须了解交集,并集。 我在学校时读过关于集合论的文章,​​但现在已经忘记了。 您可以将数组视为集合并对其执行许多操作。 以下是一些我在 irb 上试过的例子,让我们参加一个大学排球队,其中有些人叫 Ashok,Chavan,Karthik,Jesus 和 Budha。 如果您列出板球队的名单,那就有 Budha,Karthik,Ragu 和 Ram。 现在让我们用 ruby 对其进行编码。 为了收集排球队成员,我们创建了一个数组,如下所示
对于那些了解集合论的人,你必须了解交集,并集。 我在学校时读过关于集合论的文章,​​但现在已经忘记了。 你可以将数组视为集合并对其执行许多操作。 以下是一些我在 irb 上试过的例子,让我们参加一个大学排球队,其中有些人叫 Ashok,Chavan,Karthik,Jesus 和 Budha。 如果你列出板球队的名单,那就有 Budha,Karthik,Ragu 和 Ram。 现在让我们用 ruby 对其进行编码。 为了收集排球队成员,我们创建了一个数组,如下所示
```rb
>> volleyball=["Ashok", "Chavan", "Karthik", "Jesus", "Budha"]
......@@ -330,7 +330,7 @@ ArgumentError: wrong number of arguments (3 for 2)
=> ["Ashok", "Chavan", "Karthik", "Jesus", "Budha", "Ragu", "Ram"]
```
所见,我们获得了排球队和板球队成员的名字。 | (或)运算符不同于+(加号)运算符。 让我们增加排球队和板球队
所见,我们获得了排球队和板球队成员的名字。 | (或)运算符不同于+(加号)运算符。 让我们增加排球队和板球队
```rb
>> volleyball + cricket
......@@ -346,11 +346,11 @@ ArgumentError: wrong number of arguments (3 for 2)
=> ["Ashok", "Chavan", "Jesus"]
```
因此,我们看到排球队中只有三名球员。 因此,如果您是数学家,您会对 Ruby 感到满意。
因此,我们看到排球队中只有三名球员。 因此,如果你是数学家,你会对 Ruby 感到满意。
### 6.4。 空数组为真
Ruby 开发人员还必须了解其他内容。 它关于条件和空数组。 启动的 irb 并输入
Ruby 开发人员还必须了解其他内容。 它关于条件和空数组。 启动的 irb 并输入
```rb
>> puts "A" if []
......@@ -358,7 +358,7 @@ A
=> nil
```
如果您看到的话,即使传递给`if`语句的数组为空,该语句也会打印 A。 这有点违背了最不令人惊讶的理论,但是请不要感到惊讶。 有一个书架,里面有书,所以如果您这样说
如果你看到的话,即使传递给`if`语句的数组为空,该语句也会打印 A。 这有点违背了最不令人惊讶的理论,但是请不要感到惊讶。 有一个书架,里面有书,所以如果你这样说
```rb
>> puts "Books Present" if ["treasure island", "I Love Ruby"]
......@@ -419,7 +419,7 @@ a is not empty
### 6.5。 压缩阵列
有时一个数组可能包含`nil`值,而您想删除它,在这种情况下,您可以在该数组上调用`compact`。 让我们尝试一个例子。 启动您的 irb 或 pry,然后输入以下内容
有时一个数组可能包含`nil`值,而你想删除它,在这种情况下,你可以在该数组上调用`compact`。 让我们尝试一个例子。 启动你的 irb 或 pry,然后输入以下内容
首先让我们初始化数组
......@@ -442,7 +442,7 @@ a is not empty
=> [1, nil, 2, nil, 3, nil]
```
令我们沮丧的是,仍然保留了零值,真正发生了什么? 好吧,当`a`上调用 compact 时,将创建一个新的压缩数组,并将其返回给我们的 REPL &lt;sup class="footnote"&gt;[ [24](#_footnotedef_24 "View footnote.") ]&lt;/sup&gt; ,然后 REPL 将其打印出来。 那么如何使`a`真正改变呢? 如下所示,带有 bang 或`compact!`的简单调用紧凑型;)
令我们沮丧的是,仍然保留了零值,真正发生了什么? 好吧,当`a`上调用 compact 时,将创建一个新的压缩数组,并将其返回给我们的 REPL &lt;sup class="footnote"&gt;[ [24](#_footnotedef_24 "View footnote.") ]&lt;/sup&gt; ,然后 REPL 将其打印出来。 那么如何使`a`真正改变呢? 如下所示,带有 bang 或`compact!`的简单调用紧凑型;)
```rb
>> a.compact!
......@@ -472,14 +472,14 @@ Ruby 带有非常强大的数组操作,我们将看到如何在易于使用的
现在,它取第二个值,即 2,并且发生相同的过程,现在返回数组为`[1, 4]`,类似地,返回数组最终变为`[1, 4, 9]`并返回。
`collect`不会修改调用它的对象,因此,如果查看`array`是什么,它仍将与下面的显示相同
`collect`不会修改调用它的对象,因此,如果查看`array`是什么,它仍将与下面的显示相同
```rb
>> array
=> [1, 2, 3]
```
可以在 irb 中检查它。 如果要收集以修改被调用的对象,请使用爆炸符号,如下所示
可以在 irb 中检查它。 如果要收集以修改被调用的对象,请使用爆炸符号,如下所示
```rb
>> array.collect!{ |element| element * element }
......
......@@ -98,7 +98,7 @@ Total marks = 195
在上面的程序中,我们计算了哈希`mark`中存储的所有标记的总数。 注意我们如何使用`each`循环。 请注意,我们在循环体中使用`|key,value|`获得了键值对。 `key`保留哈希的索引,`value`保留存储在该特定索引 &lt;sup class="footnote"&gt;[ [25](#_footnotedef_25 "View footnote.") ]&lt;/sup&gt; 处的值。 每次执行循环时,我们都将值加到 total,因此最后,变量 total 获得了散列中存储的值的总数。 最后,我们打印出总数。
下面是另一个将学生标记存储在哈希中的程序,我们使用 each 循环打印与`key`对应的`key``value`。 希望已经足够了解,可以自行解释以下代码。
下面是另一个将学生标记存储在哈希中的程序,我们使用 each 循环打印与`key`对应的`key``value`。 希望已经足够了解,可以自行解释以下代码。
```rb
#!/usr/bin/ruby
......@@ -125,7 +125,7 @@ Math => 70
### 7.3。 散列创建的更多方法
还有另一种创建哈希的方法,让我们来看一下。 参见下文,该程序的解释与先前程序 [hash_looping_1.rb](code/hash_looping_1.rb) 的解释相同,不同之处在于以下程序中的突出显示的行。 希望能自己解释一下这些程序。
还有另一种创建哈希的方法,让我们来看一下。 参见下文,该程序的解释与先前程序 [hash_looping_1.rb](code/hash_looping_1.rb) 的解释相同,不同之处在于以下程序中的突出显示的行。 希望能自己解释一下这些程序。
```rb
#!/usr/bin/ruby
......@@ -148,7 +148,7 @@ Math => 70
### 7.4。 使用符号
通常在哈希中,我们使用符号作为键而不是字符串。 这是因为与 String 相比,Symbol 占用的空间要少得多。 速度和空间要求的差异现在可能对您并不明显,但是如果您编写的程序会创建成千上万的哈希,则可能会付出巨大的代价。 因此,请尝试使用符号代替字符串。
通常在哈希中,我们使用符号作为键而不是字符串。 这是因为与 String 相比,Symbol 占用的空间要少得多。 速度和空间要求的差异现在可能对你并不明显,但是如果你编写的程序会创建成千上万的哈希,则可能会付出巨大的代价。 因此,请尝试使用符号代替字符串。
那么什么是符号? 通过在终端中输入`irb --simple-prompt`来激活我们的 irb。 在其中键入以下内容
......@@ -219,7 +219,7 @@ mark[:Math] = 70
mark[:Science] = 75
```
接下来,我们提示用户使用打印“输入主题名称:”输入标记,然后输入主题名称。 现在看下一行,首先我们使用`gets.chop`将主题名称放入变量`sub`中。 `chop`会删除您在按下键盘上的 Enter 键时输入的输入字符`\n``to_sym`将您输入的任何内容转换为符号,所有这些最终存储在`sub`中。
接下来,我们提示用户使用打印“输入主题名称:”输入标记,然后输入主题名称。 现在看下一行,首先我们使用`gets.chop`将主题名称放入变量`sub`中。 `chop`会删除你在按下键盘上的 Enter 键时输入的输入字符`\n``to_sym`将你输入的任何内容转换为符号,所有这些最终存储在`sub`中。
```rb
sub = gets.chop.to_sym
......@@ -231,7 +231,7 @@ sub = gets.chop.to_sym
puts "Mark in #{sub} is #{mark[sub]}"
```
因此,已经看到了该程序 [hash_creation_1.rb](code/hash_creation_1.rb) ,我们现在已经了解符号,因此可以将其编写如下:
因此,已经看到了该程序 [hash_creation_1.rb](code/hash_creation_1.rb) ,我们现在已经了解符号,因此可以将其编写如下:
```rb
#!/usr/bin/ruby
......@@ -254,7 +254,7 @@ Science => 75
参见`marks = { :English ⇒ 50, :Math ⇒ 70, :Science ⇒ 75 }`行,我们在这里使用符号而不是字符串作为哈希键。 与字符串相比,哈希具有一些优势,因为与字符串相比,它们占用的内存更少(在程序运行期间)。
在 ruby 1.9 及更高版本中,有更好的写 [hash_creation_1_a.rb](code/hash_creation_1_a.rb) 的方法,可以在下面提到的 [hash_creation_2.rb](code/hash_creation_2.rb) 中看到。 只需在下面的程序中查看此`marks = { English: 50, Math: 70, Science: 75 }`
在 ruby 1.9 及更高版本中,有更好的写 [hash_creation_1_a.rb](code/hash_creation_1_a.rb) 的方法,可以在下面提到的 [hash_creation_2.rb](code/hash_creation_2.rb) 中看到。 只需在下面的程序中查看此`marks = { English: 50, Math: 70, Science: 75 }`
```rb
#!/usr/bin/ruby
......@@ -271,7 +271,7 @@ marks.each { |a,b|
### 7.5。 字符串,冻结的字符串&符号,它们的存储足迹
字符串占用大量内存,让我们看一个例子,启动的 irb 并输入以下代码
字符串占用大量内存,让我们看一个例子,启动的 irb 并输入以下代码
```rb
>> c = "able was i ere i saw elba"
......@@ -286,7 +286,7 @@ marks.each { |a,b|
在上面的示例中,我们看到了两个变量`c``d`,它们都分配给相同的字符串“ able is ire ere elba”,但是如果我通过调用`c.object_id``d.object_id`看到对象 ID 是 ,两者是不同的。 这意味着这两个“可能是我看见了厄尔巴岛”存储在不同的位置。 它们被复制并复制。
这意味着,假设在程序中的多个位置声明了相同的字符串,并且所有字符串都将占用新的内存,因此这将导致计算机 RAM 上的大量负载(对于大型程序)。
这意味着,假设在程序中的多个位置声明了相同的字符串,并且所有字符串都将占用新的内存,因此这将导致计算机 RAM 上的大量负载(对于大型程序)。
现在让我们看看如果我们使用一种称为冻结字符串的新事物会发生什么。 在 irb 中输入以下代码
......@@ -318,7 +318,7 @@ marks.each { |a,b|
因此,在上面的示例中,我们将`e`和`f`分配给符号`:some_symbol`,当我们检查它们的对象 ID 时,它们都是相同的,或者它们都指向相同的位置。 这意味着,如果我们一次又一次地声明符号,它们将不会占用额外的空间。 冻结的字符串和符号对于存储很有用。 普通的字符串是不好的。
那我为什么要在哈希部分说这个呢? 假设看到了这段代码
那我为什么要在哈希部分说这个呢? 假设看到了这段代码
```rb
>> person = {"name" => "frank"}
......@@ -355,7 +355,7 @@ and you have this one
### 7.7。 转换哈希值
假设您有一个 Hash 对象,并且想要转换其值。 假设您有一个哈希,其值是数字,并且想要将其转换为它们的平方,然后在该 Hash 实例上使用 transform_values 函数。 让我们来看看代码,看看它是如何工作的。 点火或撬动
假设你有一个 Hash 对象,并且想要转换其值。 假设你有一个哈希,其值是数字,并且想要将其转换为它们的平方,然后在该 Hash 实例上使用 transform_values 函数。 让我们来看看代码,看看它是如何工作的。 点火或撬动
首先定义一个哈希,如下所示
......@@ -371,7 +371,7 @@ and you have this one
=> {:a=>1, :b=>4, :c=>9}
```
如果注意到,它的功能与在 Array 中收集非常相似,但适用于 Hash 中的值。
如果注意到,它的功能与在 Array 中收集非常相似,但适用于 Hash 中的值。
现在让我们看看哈希是否已更改
......
......@@ -26,7 +26,7 @@ Output
bad, bae, baf, bag, => "bad".."bag"
```
让我们尝试一下 irb 中的其他一些例子,这些例子会告诉我们更多有关 Ranges 的信息。 因此,启动的 irb 并输入以下内容
让我们尝试一下 irb 中的其他一些例子,这些例子会告诉我们更多有关 Ranges 的信息。 因此,启动的 irb 并输入以下内容
```rb
>> a = -4..10
......@@ -187,7 +187,7 @@ letter = gets.chop
### 8.4。 无尽的范围
Ruby 有无限的范围,也就是说可以编写这样的程序
Ruby 有无限的范围,也就是说可以编写这样的程序
```rb
#!/usr/bin/ruby
......
## 9.功能
您多次使用同一段代码时,可以将它们分组为一个函数,您可以在程序中的任何位置调用该分组代码以执行特定任务。 让我们以一个现实世界为例,您去旅馆,侍者走近,您点了一份炸鱼,就明白了。 订购后,您不会受到任何影响。
你多次使用同一段代码时,可以将它们分组为一个函数,你可以在程序中的任何位置调用该分组代码以执行特定任务。 让我们以一个现实世界为例,你去旅馆,侍者走近,你点了一份炸鱼,就明白了。 订购后,你不会受到任何影响。
一旦订购了鱼苗,就会发生很多程序。 服务员记下您的订单,他去厨房,将订单交给厨师,厨师告诉他要煮熟的菜肴会花费很多时间。 服务员想着如何避免让您感到无聊,他来到您的餐桌旁,为您推荐开胃菜和/或开胃菜,为您提供可以在吃菜前喝得很好的饮料,他汇集了厨房以查看菜是否 准备好了。 如果菜已经准备好并且您已经完成了开胃菜,那么他将为您服务。 如果您还没吃完开胃菜,他会告诉厨房让菜保温,然后等您煮完。 一旦他把盘子拿到你的桌子上,他就放下装有盘子和餐具的盘子。
一旦订购了鱼苗,就会发生很多程序。 服务员记下你的订单,他去厨房,将订单交给厨师,厨师告诉他要煮熟的菜肴会花费很多时间。 服务员想着如何避免让你感到无聊,他来到你的餐桌旁,为你推荐开胃菜和/或开胃菜,为你提供可以在吃菜前喝得很好的饮料,他汇集了厨房以查看菜是否 准备好了。 如果菜已经准备好并且你已经完成了开胃菜,那么他将为你服务。 如果你还没吃完开胃菜,他会告诉厨房让菜保温,然后等你煮完。 一旦他把盘子拿到你的桌子上,他就放下装有盘子和餐具的盘子。
您要做的只是订购炸鱼,而完全忽略了后台正在运行的功能。 您向服务员下了订单(输入),然后拿到了盘子(输出)。 根据服务员的训练,服务员会预先计划或训练做什么和不做什么。
你要做的只是订购炸鱼,而完全忽略了后台正在运行的功能。 你向服务员下了订单(输入),然后拿到了盘子(输出)。 根据服务员的训练,服务员会预先计划或训练做什么和不做什么。
让我们开始使用 Ruby 中的函数。 我们将看一个程序,其中将编写一个名为`print_line`的函数,该函数将打印一行。 在文本编辑器中键入以下程序并运行它。
......@@ -36,7 +36,7 @@ def print_line
end
```
`def`告诉您正在定义一个功能。 函数必须具有名称,该名称紧随`def`关键字之后。 在这种情况下,函数的名称为`print_line`。 您可以在其中编写所需的代码。 在这种情况下,我们将创建一个包含 20 个下划线字符的行。
`def`告诉你正在定义一个功能。 函数必须具有名称,该名称紧随`def`关键字之后。 在这种情况下,函数的名称为`print_line`。 你可以在其中编写所需的代码。 在这种情况下,我们将创建一个包含 20 个下划线字符的行。
因此,我们创建了一个函数,并向其中添加了代码。 现在我们需要做的就是从程序中调用该函数。 只需在程序中键入函数名称即可,如下所示
......@@ -50,7 +50,7 @@ print_line
### 9.1。 参数传递
让我们对本节中的功能进行更多控制。 有时您不去酒店订购一顿菜,您可以订购多少或更少。 如果您和朋友一起去,可以订购更多份量;如果您一个人,则订购的份量会更少。 为什么用`print_line`功能不能做同样的事情? 为什么我们不能更改其长度,这样做将是一件很了不起的事情,我们可以根据自己的选择打印长度的行。
让我们对本节中的功能进行更多控制。 有时你不去酒店订购一顿菜,你可以订购多少或更少。 如果你和朋友一起去,可以订购更多份量;如果你一个人,则订购的份量会更少。 为什么用`print_line`功能不能做同样的事情? 为什么我们不能更改其长度,这样做将是一件很了不起的事情,我们可以根据自己的选择打印长度的行。
看下面的代码,我们在函数名称后键入了一个名为`length`的东西,它称为参数。 像函数一样,参数也有一个名称,在这种情况下,我们将其命名为`length`。 我们可以将任何值传递给它以改变打印行的`length`。 输入以下代码并执行
......@@ -70,7 +70,7 @@ end
end
```
将获得如下所示的设计模式
将获得如下所示的设计模式
```rb
__________
......@@ -100,7 +100,7 @@ end
### 9.2。 默认参数
[function_1.rb](code/function_1.rb) 中,您了解了如何将参数传递给函数。 如果假设您无法通过辩论,该怎么办? 如果这样做,将会产生一个错误,一个好的程序员将不会希望发生这种错误。 为了防止这种情况并使编程变得容易一些,最好为函数提供默认参数。 注意下面在 [function_default_argument.rb](code/function_default_argument.rb) 中给出的代码
[function_1.rb](code/function_1.rb) 中,你了解了如何将参数传递给函数。 如果假设你无法通过辩论,该怎么办? 如果这样做,将会产生一个错误,一个好的程序员将不会希望发生这种错误。 为了防止这种情况并使编程变得容易一些,最好为函数提供默认参数。 注意下面在 [function_default_argument.rb](code/function_default_argument.rb) 中给出的代码
```rb
# function_default_argument.rb
......@@ -120,11 +120,11 @@ ____________________
________________________________________
```
您可以在程序中通过输入`length = 20`来查看函数`print_line`,这表明如果未传递任何参数,则该函数必须假定`length`的值为 20。 如果通过,则此值将被您传递的任何值所覆盖。 正如您在第一个函数调用中看到的那样,我们仅通过函数名称`print_line`来调用函数,我们无需理会将长度值传递给它,但是我们看到在输出中打印出一行长度为 20 个单位的行 。
你可以在程序中通过输入`length = 20`来查看函数`print_line`,这表明如果未传递任何参数,则该函数必须假定`length`的值为 20。 如果通过,则此值将被你传递的任何值所覆盖。 正如你在第一个函数调用中看到的那样,我们仅通过函数名称`print_line`来调用函数,我们无需理会将长度值传递给它,但是我们看到在输出中打印出一行长度为 20 个单位的行 。
### 9.3。 将数组传递给函数
通常,当您将变量传递给函数时,会创建该变量的副本。 而且,如果您对变量进行了更改,则该函数外部的变量不会受到影响。 因此,让我们看看将数组传递给函数时会发生什么。 在下面的程序中键入并运行它。
通常,当你将变量传递给函数时,会创建该变量的副本。 而且,如果你对变量进行了更改,则该函数外部的变量不会受到影响。 因此,让我们看看将数组传递给函数时会发生什么。 在下面的程序中键入并运行它。
```rb
# array_passed_to_function.rb
......@@ -146,7 +146,7 @@ Output
[1, 2, 3, 4, 5, 6]
```
如果是编程新手,这可能并不奇怪,但是当将变量传递给函数时,其值不应更改。 但是在数组的情况下,在函数`array_changer`中,我们向其中添加了一个元素,并且它会更改。 好吧,这是数组传递给函数的特殊行为。
如果是编程新手,这可能并不奇怪,但是当将变量传递给函数时,其值不应更改。 但是在数组的情况下,在函数`array_changer`中,我们向其中添加了一个元素,并且它会更改。 好吧,这是数组传递给函数的特殊行为。
为避免这种情况,请尝试以下程序
......@@ -219,7 +219,7 @@ puts square_it 5
25
```
所见,我们调用了`square_it 5`,结果为 25。 这可能是因为在 Ruby 中,默认情况下返回上一次执行的语句的结果。
所见,我们调用了`square_it 5`,结果为 25。 这可能是因为在 Ruby 中,默认情况下返回上一次执行的语句的结果。
### 9.5。 关键字参数
......@@ -280,7 +280,7 @@ say_hello
### 9.6。 递归函数
让我们看看另一件事。 您可能想知道为什么我要进行所有数学运算? 某些程序员确实写了一些书,这些书尽可能地排除了数学知识,我不是专业的数学家,但我很欣赏数学。 计算机是基于数学的。 所有计算机都使用称为布尔代数的东西来执行所有任务。 我并不是说您必须是数学家才能成为程序员,但是了解数学确实会有所帮助。
让我们看看另一件事。 你可能想知道为什么我要进行所有数学运算? 某些程序员确实写了一些书,这些书尽可能地排除了数学知识,我不是专业的数学家,但我很欣赏数学。 计算机是基于数学的。 所有计算机都使用称为布尔代数的东西来执行所有任务。 我并不是说你必须是数学家才能成为程序员,但是了解数学确实会有所帮助。
好,什么是阶乘? 取一个数字,取 3,现在将是 3 X 2 X 1,即六个! 是不是很简单? 6 是 3 的阶乘。好吧,我们现在取 4,所以 4 X 3 X 2 X 1 将是 24,以类似的方式,2 的阶乘将是 2 X 1,即 2。有了这些知识,我们现在将构造一个 该程序将为我们提供一定数量的阶乘。
......@@ -301,7 +301,7 @@ number = 17
puts "Factorial of #{number} = #{factorial number}"
```
执行上面的代码,这就是得到的输出
执行上面的代码,这就是得到的输出
```rb
Factorial of 17 = 355687428096000
......@@ -362,7 +362,7 @@ end
### 9.7。 可变数量的参数
假设您不知道向一个函数传递了多少个参数,假设您正在编写一个要添加 N 个数字的函数,则 N 的值未知,那么如何获得可变数量的参数。 键入下面给出的程序 [function_variable_arguments.rb](code/function_variable_arguments.rb) 并执行它。
假设你不知道向一个函数传递了多少个参数,假设你正在编写一个要添加 N 个数字的函数,则 N 的值未知,那么如何获得可变数量的参数。 键入下面给出的程序 [function_variable_arguments.rb](code/function_variable_arguments.rb) 并执行它。
```rb
# function_variable_arguments.rb
......@@ -389,7 +389,7 @@ Others are:
5
```
因此,程序的输出如上所示。 如所见,我们将 1,2,3,4,5 作为参数传递,那么`a`只是一个变量,因此它取值为 1,其他变量被变量`**others**` **吸收( 注意,变量名前的星号** 是一种特殊的自变量,它将所有未被前一个自变量吸收的其余自变量存储在其他变量名中(作为数组)。 现在在下面的代码中
因此,程序的输出如上所示。 如所见,我们将 1,2,3,4,5 作为参数传递,那么`a`只是一个变量,因此它取值为 1,其他变量被变量`**others**` **吸收( 注意,变量名前的星号** 是一种特殊的自变量,它将所有未被前一个自变量吸收的其余自变量存储在其他变量名中(作为数组)。 现在在下面的代码中
```rb
for x in others
......
## 10.可变范围
在上一节中我们已经了解了函数,而在之前我们已经了解了变量。 我认为现在是时候输入变量范围了。 在本章中,我们将探讨在程序的特定部分中声明变量时有价值的时间或长度。 让我们从一个例子开始。 启动的文本编辑器,输入下面的代码( [variable_scope.rb](code/variable_scope.rb) )并执行它。
在上一节中我们已经了解了函数,而在之前我们已经了解了变量。 我认为现在是时候输入变量范围了。 在本章中,我们将探讨在程序的特定部分中声明变量时有价值的时间或长度。 让我们从一个例子开始。 启动的文本编辑器,输入下面的代码( [variable_scope.rb](code/variable_scope.rb) )并执行它。
```rb
#!/usr/bin/ruby
......@@ -22,9 +22,9 @@ variable_scope.rb:7:in `print_x': undefined local variable or method `x' for mai
from variable_scope.rb:10
```
好吧,你得到一个错误。 看到您已经通过输入`x = 5`声明了一个变量。 在函数`print_x`中,您告诉 ruby 程序打印出变量 x,但会引发错误。 看一下输出,它说`undefined local variable or method `x' for main:Object (NameError) from variable_scope.rb:10`,那么我们已经定义了`x`并在开始时将其分配为值 5,那么 Ruby 如何抛出错误? 好吧,我们在函数`print_x`之外定义了`x`,因此`x`内部没有作用域,因此会出现错误。
好吧,你得到一个错误。 看到你已经通过输入`x = 5`声明了一个变量。 在函数`print_x`中,你告诉 ruby 程序打印出变量 x,但会引发错误。 看一下输出,它说`undefined local variable or method `x' for main:Object (NameError) from variable_scope.rb:10`,那么我们已经定义了`x`并在开始时将其分配为值 5,那么 Ruby 如何抛出错误? 好吧,我们在函数`print_x`之外定义了`x`,因此`x`内部没有作用域,因此会出现错误。
优秀的程序员可以利用编程语言提供的优势,并且足够聪明,可以按其施加的规则和限制发挥作用。 对于新手来说,我们无法访问我们在函数外部分配的变量似乎是一个真正的障碍,但是当您的程序成为成熟的程序员时,您会变相地实现它的祝福。
优秀的程序员可以利用编程语言提供的优势,并且足够聪明,可以按其施加的规则和限制发挥作用。 对于新手来说,我们无法访问我们在函数外部分配的变量似乎是一个真正的障碍,但是当你的程序成为成熟的程序员时,你会变相地实现它的祝福。
要了解更多信息,请在文本编辑器中键入以下程序(variable_scope_1.rb)并执行。
......@@ -50,7 +50,7 @@ Output
5
```
仔细看一下输出。 首先在程序中声明变量`x = 5`,然后在函数`print_x`中声明变量`x = 3`。 注意,在函数`print_x`中声明的变量与在函数外部声明的变量不同。 接下来,我们调用函数`print_x`,该函数将输出打印为 3,这是预期的结果,因为在`print_x`内部我们在`x = 3`之后编写了`puts x`。 下一个语句是此处的英雄,(在函数外)我们在`print_x`之后写了`puts x`,如果您希望打印 3,则您错了。 这里`x`是我们在函数外部声明的`x`,在这里它将被打印为 5。这意味着在函数内部声明的变量在其外部没有作用域。
仔细看一下输出。 首先在程序中声明变量`x = 5`,然后在函数`print_x`中声明变量`x = 3`。 注意,在函数`print_x`中声明的变量与在函数外部声明的变量不同。 接下来,我们调用函数`print_x`,该函数将输出打印为 3,这是预期的结果,因为在`print_x`内部我们在`x = 3`之后编写了`puts x`。 下一个语句是此处的英雄,(在函数外)我们在`print_x`之后写了`puts x`,如果你希望打印 3,则你错了。 这里`x`是我们在函数外部声明的`x`,在这里它将被打印为 5。这意味着在函数内部声明的变量在其外部没有作用域。
要了解更多信息并说服函数内部声明的变量在函数外部没有作用域,我们将尝试另一个程序。 在文本编辑器中输入程序 [variable_scope_2.rb](code/variable_scope_2.rb) 并执行它。
......@@ -98,11 +98,11 @@ Output
variable_scope_3.rb:4: undefined local variable or method `a' for main:Object (NameError)
```
如果预期正确,程序将抛出错误。 我们已经在声明`a`之前给了`puts a`。 Ruby 解释器不会考虑将来声明的内容,因此,在遇到`puts a`时,此时将不会声明`a`,因此会引发错误。 换句话说,变量的作用域仅在声明后才开始。
如果预期正确,程序将抛出错误。 我们已经在声明`a`之前给了`puts a`。 Ruby 解释器不会考虑将来声明的内容,因此,在遇到`puts a`时,此时将不会声明`a`,因此会引发错误。 换句话说,变量的作用域仅在声明后才开始。
### 10.1。 全局变量
如果不喜欢无法从函数外部访问声明的变量的想法,那么 Ruby 提供了一种方法。 有一些称为全局变量的特殊变量,可以从任何地方访问。 全局变量前面带有美元($)符号。 要了解全局变量,请看一个示例。 在下面键入程序( [global_variables.rb](code/global_variables.rb) )并执行它。
如果不喜欢无法从函数外部访问声明的变量的想法,那么 Ruby 提供了一种方法。 有一些称为全局变量的特殊变量,可以从任何地方访问。 全局变量前面带有美元($)符号。 要了解全局变量,请看一个示例。 在下面键入程序( [global_variables.rb](code/global_variables.rb) )并执行它。
```rb
#!/usr/bin/ruby
......@@ -126,7 +126,7 @@ Output
3
```
成功运行它,让我们看看它是如何工作的。 首先,我们声明一个全局变量$ x 并将其分配给语句`$x = 5`中的值 5。 接下来,我们定义一个函数`print_x`,其中使用语句`$x = 3`将`$x`的值更改为 3,然后使用`puts $x`打印`$x`的值。 因此,显然我们调用`print_x`,将得到的输出为 3。接下来,在调用`print_x`之后的函数外部,我们将使用`puts $x`打印`$x`的值。 如果您认为它将打印出 5,那么您就错了。 由于可以从任何位置访问`$x`,因此我们将其称为`print_x`,在`print_x`中,无论如何,我们都将`$x`的值更改为 3,即使在函数范围之外,也将`$x`的值更改为 `$x`将被更改。
成功运行它,让我们看看它是如何工作的。 首先,我们声明一个全局变量$ x 并将其分配给语句`$x = 5`中的值 5。 接下来,我们定义一个函数`print_x`,其中使用语句`$x = 3`将`$x`的值更改为 3,然后使用`puts $x`打印`$x`的值。 因此,显然我们调用`print_x`,将得到的输出为 3。接下来,在调用`print_x`之后的函数外部,我们将使用`puts $x`打印`$x`的值。 如果你认为它将打印出 5,那么你就错了。 由于可以从任何位置访问`$x`,因此我们将其称为`print_x`,在`print_x`中,无论如何,我们都将`$x`的值更改为 3,即使在函数范围之外,也将`$x`的值更改为 `$x`将被更改。
让我们来看另一个示例,以更好地理解全局变量。 查看下面的示例( [global_variables_1.rb](code/global_variables_1.rb) ),在文本编辑器中键入并执行它
......
此差异已折叠。
## 12.安全导航
Ruby 努力成为程序员最好的朋友。 它的制造商正在发明新的方法来改善的编码体验。 Ruby 2.3 中的此类改进之一是安全导航。 或者一种写不会引发意外错误的条件的方法。 请参阅下面的程序,键入并执行
Ruby 努力成为程序员最好的朋友。 它的制造商正在发明新的方法来改善的编码体验。 Ruby 2.3 中的此类改进之一是安全导航。 或者一种写不会引发意外错误的条件的方法。 请参阅下面的程序,键入并执行
```rb
# safe_navigation.rb
......
## 13.打破大型程序
并不是说您将编写全部放在一个文件中的专业程序。 您需要将它们分解成小块,将这些块放入单独的文件中,并根据需要将它们包括在其他程序中。 所以让我们看一个例子
并不是说你将编写全部放在一个文件中的专业程序。 你需要将它们分解成小块,将这些块放入单独的文件中,并根据需要将它们包括在其他程序中。 所以让我们看一个例子
```rb
# break_full.rb
......@@ -24,7 +24,7 @@ puts "The squares perimeter is #{s.perimeter}"
The squares perimeter is 20
```
因此,会看到上述名为 [break_full.rb](code:break_full.rb) 的程序,该程序具有类定义,然后是一段代码,使用该定义来计算侧面 5 个单位的平方周长。
因此,会看到上述名为 [break_full.rb](code:break_full.rb) 的程序,该程序具有类定义,然后是一段代码,使用该定义来计算侧面 5 个单位的平方周长。
如果`Square`代码可以放入一个单独的文件中,从而可能需要在许多其他程序中将其用作需要的地方,这是否合乎逻辑? 如果程序很大,我们可以将它们分成较小的文件,并按逻辑命名它们,以使其易于阅读,重用和调试。
......
......@@ -19,19 +19,19 @@ puts "Hello, I am #{p.name}, age #{p.age}"
Hello, I am Karthik, age 30
```
好了,现在让我们看看它是如何工作的。 首先,将使用此语句创建新的`Struct`类型
好了,现在让我们看看它是如何工作的。 首先,将使用此语句创建新的`Struct`类型
```rb
Struct.new :name, :age
```
现在,要命名它,以便可以使用它,将其命名为`person`
现在,要命名它,以便可以使用它,将其命名为`person`
```rb
person = Struct.new :name, :age
```
命名后,此变量`person`的作用类似于`class`可以像这样声明它的新实例
命名后,此变量`person`的作用类似于`class`可以像这样声明它的新实例
```rb
p = person.new
......@@ -46,13 +46,13 @@ p.name = "Karthik"
p.age = 30
```
然后可以打印数据,如下所示
然后可以打印数据,如下所示
```rb
puts "Hello, I am #{p.name}, age #{p.age}"
```
而已。 在不使用`class`的情况下,创建了一个数据结构并使用了它! 你不觉得它很棒吗?
而已。 在不使用`class`的情况下,创建了一个数据结构并使用了它! 你不觉得它很棒吗?
并不是`person = Struct.new :name, :age`中的`person`应该是可变的(即以小写字母开头),但是它也可以像`Person`一样是常量。 这就是这里的下一段代码中的确切内容
......@@ -82,7 +82,7 @@ p = Person.new
我们已经将`Person`与大写字母 P 结合使用,并且代码有效!
如果担心在上一个程序中需要输入很多字符,可以如下所示将其缩短。 请看下面的代码。
如果担心在上一个程序中需要输入很多字符,可以如下所示将其缩短。 请看下面的代码。
```rb
# struct_one_line.rb
......@@ -112,9 +112,9 @@ p.name = "Karthik"
p.age = 30
```
如果注意到正确的话,`p = person.new "Karthik", 30`看起来不是类中的构造函数吗?
如果注意到正确的话,`p = person.new "Karthik", 30`看起来不是类中的构造函数吗?
并非`Struct`仅限于其属性数据结构。 可以具有一个`Struct`实例可以调用的功能,如下面的程序所示。 输入并执行。
并非`Struct`仅限于其属性数据结构。 可以具有一个`Struct`实例可以调用的功能,如下面的程序所示。 输入并执行。
```rb
include:code/struct_about_me.rb[]
......@@ -126,7 +126,7 @@ Output
Hello, I am Karthik, age 30
```
您所见,在 Struct 的`do end`块之间定义了一个名为`about_me`的函数。 我们在此行`p = person.new "Karthik", 30`中声明一个人`p`,然后像`puts p.about_me`这样调用`p`上的`about_me`函数,程序运行正常。 您还必须注意,我们可以将参数传递给 struct 中的函数,但是由于我的懒惰,我没有显示该示例。
你所见,在 Struct 的`do end`块之间定义了一个名为`about_me`的函数。 我们在此行`p = person.new "Karthik", 30`中声明一个人`p`,然后像`puts p.about_me`这样调用`p`上的`about_me`函数,程序运行正常。 你还必须注意,我们可以将参数传递给 struct 中的函数,但是由于我的懒惰,我没有显示该示例。
现在让我们看看如何以错误的方式进行结构化。 在下面输入程序并执行
......@@ -148,7 +148,7 @@ Output
struct_wrong.rb:7:in `<main>': undefined method `profession=' for #<struct name="Karthik", age=30> (NoMethodError)
```
如果您得到如上所示的输出,则表明您正确键入了该程序。 问题出在`p.profession = "Engineer"`行中,我们正在将数据分配给尚未在结构`person = Struct.new :name, :age`中声明的名为职业的属性。 因此会引发错误。 为了避免这些事情,您可以使用下面的程序中所示的 Open Struct
如果你得到如上所示的输出,则表明你正确键入了该程序。 问题出在`p.profession = "Engineer"`行中,我们正在将数据分配给尚未在结构`person = Struct.new :name, :age`中声明的名为职业的属性。 因此会引发错误。 为了避免这些事情,你可以使用下面的程序中所示的 Open Struct
```rb
# open_struct.rb
......
## 15\. Rdoc
您正在阅读本书是因为您正在寻找某种文档来开始使用 Ruby 进行编程。 文档在任何类型的编程中都非常重要。 为所编写的代码保留良好的文档记录可能会使您与优秀的程序员区分开来,并使您成为一个受追捧的人。 本章告诉您两件事,首先是 Ruby 的核心文档在哪里,以及如何查找和阅读它。 第二,它教您如何生成文档,以便其他人可以更好地理解您的程序。
你正在阅读本书是因为你正在寻找某种文档来开始使用 Ruby 进行编程。 文档在任何类型的编程中都非常重要。 为所编写的代码保留良好的文档记录可能会使你与优秀的程序员区分开来,并使你成为一个受追捧的人。 本章告诉你两件事,首先是 Ruby 的核心文档在哪里,以及如何查找和阅读它。 第二,它教你如何生成文档,以便其他人可以更好地理解你的程序。
### 15.1。 阅读 Ruby 文档
假设您想了解 Ruby 程序中的 String 类。 您想知道如何使用 Ruby 来计算姓名中的字符数,那么该怎么做呢? 访问此链接 [http://ruby-doc.org/](http://ruby-doc.org/) ,这是可获取红宝石文档的集中位置。 现在,如果您可以进行一些操作,您会发现一个东西/链接,例如:2.1.4 core-Ruby 2.1.4 的 Core API 文档。 单击它,您将定向到此链接: [http://ruby-doc.org/core-2.1.4/](http://ruby-doc.org/core-2.1.4/) ,此处记录了 2.1.4 的核心库。
假设你想了解 Ruby 程序中的 String 类。 你想知道如何使用 Ruby 来计算姓名中的字符数,那么该怎么做呢? 访问此链接 [http://ruby-doc.org/](http://ruby-doc.org/) ,这是可获取红宝石文档的集中位置。 现在,如果你可以进行一些操作,你会发现一个东西/链接,例如:2.1.4 core-Ruby 2.1.4 的 Core API 文档。 单击它,你将定向到此链接: [http://ruby-doc.org/core-2.1.4/](http://ruby-doc.org/core-2.1.4/) ,此处记录了 2.1.4 的核心库。
可能会出现一个问题,如何找出使用的红宝石的版本? 在终端类型 ruby -v 中,它将抛出如下输出:ruby 1.9.3p194(2012-04-20 修订版 35410)[x86_64-linux],请查看突出显示的代码段,这告诉我我正在使用 ruby 1.9.3 分 194。 谁在乎 p194 是什么? 我知道我使用的是 ruby 1.9.3,所以我要看它的文档!
可能会出现一个问题,如何找出使用的红宝石的版本? 在终端类型 ruby -v 中,它将抛出如下输出:ruby 1.9.3p194(2012-04-20 修订版 35410)[x86_64-linux],请查看突出显示的代码段,这告诉我我正在使用 ruby 1.9.3 分 194。 谁在乎 p194 是什么? 我知道我使用的是 ruby 1.9.3,所以我要看它的文档!
好的,在 [http://ruby-doc.org/core-2.5.1/](http://ruby-doc.org/core-2.5.1/) 中,您需要浏览 String,如果这样做,您会找到以下链接: [http:// ruby​​- doc.org/core-2.5.1/String.html](http://ruby-doc.org/core-2.5.1/String.html) ,这是 String 类文档所在的位置。 您可以通过很长的时间(几乎涵盖所有内容)或在顶部搜索栏中键入 String 来获得此文档,在这种情况下,Rdoc 将显示有效的搜索结果。
好的,在 [http://ruby-doc.org/core-2.5.1/](http://ruby-doc.org/core-2.5.1/) 中,你需要浏览 String,如果这样做,你会找到以下链接: [http:// ruby​​- doc.org/core-2.5.1/String.html](http://ruby-doc.org/core-2.5.1/String.html) ,这是 String 类文档所在的位置。 你可以通过很长的时间(几乎涵盖所有内容)或在顶部搜索栏中键入 String 来获得此文档,在这种情况下,Rdoc 将显示有效的搜索结果。
下图显示我通过在标有 Classes 的文本框中键入 Sting 来过滤 Ruby 中的类。 这将帮助我轻松过滤结果/类。
![rdoc 75999](img/146a2600a64e6ad8e1ef36b731702424.jpg)
好的,然后,如果您安装正确,请单击字符串将您带到此处 [http://ruby-doc.org/core-2.2.2/String.html](http://ruby-doc.org/core-2.2.2/String.html) 并向下浏览,您会找到 称为#length 的东西,当单击时会滚动到此处 [http://ruby-doc.org/core-2.2.2/String.html#method-i-length](http://ruby-doc.org/core-2.2.2/String.html#method-i-length) ,所以它确实说我们有东西 /函数/方法称为长度,另一项称为大小。
好的,然后,如果你安装正确,请单击字符串将你带到此处 [http://ruby-doc.org/core-2.2.2/String.html](http://ruby-doc.org/core-2.2.2/String.html) 并向下浏览,你会找到 称为#length 的东西,当单击时会滚动到此处 [http://ruby-doc.org/core-2.2.2/String.html#method-i-length](http://ruby-doc.org/core-2.2.2/String.html#method-i-length) ,所以它确实说我们有东西 /函数/方法称为长度,另一项称为大小。
通过有根据的猜测,我们必须能够知道这就是字符串长度的原因,让我们在 irb 上进行尝试
......@@ -26,11 +26,11 @@ $ irb --simple-prompt
=> 15
```
这样就行了! 基本的事情是到达 [http://ruby-doc.org/](http://ruby-doc.org/) 并打破头脑,这将使事情发展,并使开始了解阅读 Ruby 文档。
这样就行了! 基本的事情是到达 [http://ruby-doc.org/](http://ruby-doc.org/) 并打破头脑,这将使事情发展,并使开始了解阅读 Ruby 文档。
### 15.2。 建立文件
因此,无论您希望还是希望,您可能会或可能不知道阅读 ruby 的文档。 让我们看看如何创建一个。 确定,在名为 [rdoc_square.rb](code/rdoc_square.rb) 的文档中键入以下代码,或使用您喜欢的任何名称。 为简单起见,将其放入文件夹,并确保该文件夹中没有其他文件。
因此,无论你希望还是希望,你可能会或可能不知道阅读 ruby 的文档。 让我们看看如何创建一个。 确定,在名为 [rdoc_square.rb](code/rdoc_square.rb) 的文档中键入以下代码,或使用你喜欢的任何名称。 为简单起见,将其放入文件夹,并确保该文件夹中没有其他文件。
```rb
#rdoc_square.rb
......@@ -54,11 +54,11 @@ class Square
end
```
请注意,我是如何在属性和功能之前添加注释 &lt;sup class="footnote"&gt;[ [36](#_footnotedef_36 "View footnote.") ]&lt;/sup&gt; 的。 现在,导航到 [rdoc_square.rb](code/rdoc_square.rb) 所在的文件夹(使用控制台/终端),然后键入此命令`rdoc`,就是这样,神奇的事情发生了。 会发现创建了一个名为 doc 的文件夹,只需导航到该文件夹​​并打开名为 index.html 的文件,然后可以单击 Classs and Modules Index 框中的 Square 链接即可获得一个漂亮的文档,如图所示。
请注意,我是如何在属性和功能之前添加注释 &lt;sup class="footnote"&gt;[ [36](#_footnotedef_36 "View footnote.") ]&lt;/sup&gt; 的。 现在,导航到 [rdoc_square.rb](code/rdoc_square.rb) 所在的文件夹(使用控制台/终端),然后键入此命令`rdoc`,就是这样,神奇的事情发生了。 会发现创建了一个名为 doc 的文件夹,只需导航到该文件夹​​并打开名为 index.html 的文件,然后可以单击 Classs and Modules Index 框中的 Square 链接即可获得一个漂亮的文档,如图所示。
![rdoc 7e5a8](img/20cbf2ec86f0b2d275d3dc178ae27666.jpg)
在上图中的“属性”部分中,可以看到 side_length 属性的文档,正下方显示的是它的文档,其读取正方形边的长度。 现在检查代码 [rdoc_example.rb](code/rdoc_example.rb) 检查以下两行
在上图中的“属性”部分中,可以看到 side_length 属性的文档,正下方显示的是它的文档,其读取正方形边的长度。 现在检查代码 [rdoc_example.rb](code/rdoc_example.rb) 检查以下两行
```rb
class Square
......@@ -69,7 +69,7 @@ class Square
end
```
我们刚刚在文档页面上的`attr_accessor :side_length`之前添加了一条注释行。 这样,rdoc 决定要放置什么文档。 它只是检查在声明类,变量和函数定义之前发生了什么注释,并将其放入文档中,将其整齐地打包,放入漂亮的 CSS(即样式)和 Javascript(即动态效果&lt;sup class="footnote"&gt;[ [37](#_footnotedef_37 "View footnote.") ]&lt;/sup&gt; ),并准备将其提供给您参考。 您可以将代码以及 doc 文件夹分发给其他人以供参考,这样人们就可以更好地了解您的代码,而无需遍历所有的 ruby 编码。
我们刚刚在文档页面上的`attr_accessor :side_length`之前添加了一条注释行。 这样,rdoc 决定要放置什么文档。 它只是检查在声明类,变量和函数定义之前发生了什么注释,并将其放入文档中,将其整齐地打包,放入漂亮的 CSS(即样式)和 Javascript(即动态效果&lt;sup class="footnote"&gt;[ [37](#_footnotedef_37 "View footnote.") ]&lt;/sup&gt; ),并准备将其提供给你参考。 你可以将代码以及 doc 文件夹分发给其他人以供参考,这样人们就可以更好地了解你的代码,而无需遍历所有的 ruby 编码。
这些是生成文档的步骤
......@@ -77,4 +77,4 @@ end
* 通过终端导航到该文件夹​​,然后键入 rdoc
* 您将看到一个名为 doc 的文件夹已创建,只需进入该文件夹并启动文件 index.html
\ No newline at end of file
* 你将看到一个名为 doc 的文件夹已创建,只需进入该文件夹并启动文件 index.html
\ No newline at end of file
## 16\. Ruby 样式指南
因此,已经了解了 Ruby 编程的基础知识,并且可能已经知道如何查找 Rdoc。 本章将介绍 Ruby 样式指南。 一旦每个软件公司都有一种编码风格,那么当一个软件公司被引入公司时,必须遵循一本定义编码风格的庞大手册,这真是地狱。
因此,已经了解了 Ruby 编程的基础知识,并且可能已经知道如何查找 Rdoc。 本章将介绍 Ruby 样式指南。 一旦每个软件公司都有一种编码风格,那么当一个软件公司被引入公司时,必须遵循一本定义编码风格的庞大手册,这真是地狱。
随着互联网和协作的蓬勃发展以及邪恶的发展,Microsoft 被自由软件 &lt;sup class="footnote"&gt;[ [38](#_footnotedef_38 "View footnote.") ]&lt;/sup&gt; 击败,通用性得到发展,语言开始具有更为开放和民主的定义方式,而不受其控制。 很少的公司及其卫星公司。 因此,Ruby 也有自己的样式指南。
如果您遵循它,并且如果其他 Rubyist 看到您的代码,那么您可能会成为受人尊敬的开发人员。 您可以在 [https://github.com/bbatsov/ruby-style-guide](https://github.com/bbatsov/ruby-style-guide) 上获得有关 Ruby 样式指南的所有信息。 希望您能跟随它成为一名骄傲的 Rubyist。
\ No newline at end of file
如果你遵循它,并且如果其他 Rubyist 看到你的代码,那么你可能会成为受人尊敬的开发人员。 你可以在 [https://github.com/bbatsov/ruby-style-guide](https://github.com/bbatsov/ruby-style-guide) 上获得有关 Ruby 样式指南的所有信息。 希望你能跟随它成为一名骄傲的 Rubyist。
\ No newline at end of file
## 17.模块和混入
每当您想到模块时,便会想到一个盒子或其他东西。 只需看看您的打印机即可。 它是一个模块。 它可以做一些事情。 它有事要做。 以类似的方式,Ruby 中的模块可以包含 Ruby 代码来执行某些操作。 模块是将 Ruby 代码打包到可能的逻辑单元中的方法。 每当您想在模块中使用代码时,只需将其包含在 Ruby 程序中即可。
每当你想到模块时,便会想到一个盒子或其他东西。 只需看看你的打印机即可。 它是一个模块。 它可以做一些事情。 它有事要做。 以类似的方式,Ruby 中的模块可以包含 Ruby 代码来执行某些操作。 模块是将 Ruby 代码打包到可能的逻辑单元中的方法。 每当你想在模块中使用代码时,只需将其包含在 Ruby 程序中即可。
让我们看一下第一个名为 [module_function.rb](code/module_function.rb) 的模块程序。 以下程序具有两个模块,即`Star``Dollar`。 这两个模块具有称为`line`的相同功能。 请注意,在模块`Star`中的函数`line`中,我们打印一行 20 个星号(*)字符。 在模块`Dollar`中的功能`line`中,我们以类似的方式打印了一行 20 美元($)的字符。 在文本编辑器中键入程序并执行。
......@@ -69,7 +69,7 @@ Output
module_function_0.rb:15:in `<main>': undefined local variable or method `line' for main:Object (NameError)
```
所见,`line`被视为未定义的局部变量或方法 &lt;sup class="footnote"&gt;[ [39](#_footnotedef_39 "View footnote.") ]&lt;/sup&gt; 。 因此,可以说只有当模块包含在程序中时,才能访问模块中的功能。
所见,`line`被视为未定义的局部变量或方法 &lt;sup class="footnote"&gt;[ [39](#_footnotedef_39 "View footnote.") ]&lt;/sup&gt; 。 因此,可以说只有当模块包含在程序中时,才能访问模块中的功能。
可以说,我们编写了另一个模块,该模块不带任何功能,而只是其中的代码。 我写了以下程序 linclude:code / module.rb [module.rb]只是因为我想看看会发生什么。 事实证明,当模块在 Ruby 文件中编码并执行时,默认情况下将执行模块中的代码。 即使我们不包含该模块,也会发生这种情况。
......@@ -136,7 +136,7 @@ Star::line
Dollar::line
```
当我们调用`Dollar::line`时,将执行`Dollar`模块中的`line`函数。 当我们调用`Star::line`时,将执行`Star`模块中的`line`函数。 因此,当想在模块中调用函数时,请使用以下语法`&lt;module-name&gt;::&lt;function-name&gt;`
当我们调用`Dollar::line`时,将执行`Dollar`模块中的`line`函数。 当我们调用`Star::line`时,将执行`Star`模块中的`line`函数。 因此,当想在模块中调用函数时,请使用以下语法`&lt;module-name&gt;::&lt;function-name&gt;`
请注意,在模块`Star`中,我们将功能线定义为`Star.line`,而不仅仅是`line`。 同样,在模块`Dollar`中,我们将其定义为`Dollar.line`
......@@ -180,7 +180,7 @@ $$$$$$$$$$$$$$$$$$$$
@@@@@@@@@@@@@@@@@@@@
```
好的,有一些输出。 看一下以下几行
好的,有一些输出。 看一下以下几行
```rb
include At
......@@ -331,13 +331,13 @@ r2.what_u_do?
其中调用`r1.what_u_do?``输出`I govern this land`,调用`r2.what_u_do?`输出`I take measurements`。
这个故事的寓意是,可以在不同的模块中使用相同的类名称,只需使用`&lt;module-name&gt;::&lt;class-name&gt;`即可调用该类。 。
这个故事的寓意是,可以在不同的模块中使用相同的类名称,只需使用`&lt;module-name&gt;::&lt;class-name&gt;`即可调用该类。 。
### 17.3。 混合蛋白
模块的另一种用途是您可以根据需要在模块中混合代码。 这个叫做 mixin。 我们已经了解了 mixin,但我没有告诉您这是 mixin。 例如,假设您正在用 Ruby for Linux 和 Apple 机器编写某些应用程序。 您会发现某些代码仅在 Linux 上有效,而其他代码仅在 Apple 上有效,然后可以如下所示将它们分开。 Apple 组件进入 Apple 模块,Linux 组件进入 Linux 模块。
模块的另一种用途是你可以根据需要在模块中混合代码。 这个叫做 mixin。 我们已经了解了 mixin,但我没有告诉你这是 mixin。 例如,假设你正在用 Ruby for Linux 和 Apple 机器编写某些应用程序。 你会发现某些代码仅在 Linux 上有效,而其他代码仅在 Apple 上有效,然后可以如下所示将它们分开。 Apple 组件进入 Apple 模块,Linux 组件进入 Linux 模块。
假设您的朋友使用 Linux 机器并想要运行您的程序。 您需要做的就是在代码中包含 Linux,如下所示。
假设你的朋友使用 Linux 机器并想要运行你的程序。 你需要做的就是在代码中包含 Linux,如下所示。
```rb
# mixin.rb
......@@ -367,9 +367,9 @@ Output
This function contains code for Linux systems
```
调用方法`function`时,将调用`Linux`模块中的方法`function`。 简而言之,已经在程序中混入了 Linux 代码,并保留了 Apple 的东西。
调用方法`function`时,将调用`Linux`模块中的方法`function`。 简而言之,已经在程序中混入了 Linux 代码,并保留了 Apple 的东西。
让我们看看 mixin 的另一个例子。 看看下面的代码 [mixin_2.rb](code/mixin_2.rb) 。 可以说您的客户告诉他,他非常需要一个程序来计算圆的面积和球的体积。 因此,您开发了两个名为`Circle`和`Sphere`的类,并配有代码来查找面积和体积。 所以您的客户很高兴。 由于您的客户位于银河星系中,因此常数 Pi &lt;sup class="footnote"&gt;[ [41](#_footnotedef_41 "View footnote.") ]&lt;/sup&gt; 为 22 除以 7。因此,我们将`Pi`的值放在名为`Constants`的模块中,然后 使用语句`include Constants`包含在`Circle`和`Sphere`类中。 在下面的程序中键入并执行它。
让我们看看 mixin 的另一个例子。 看看下面的代码 [mixin_2.rb](code/mixin_2.rb) 。 可以说你的客户告诉他,他非常需要一个程序来计算圆的面积和球的体积。 因此,你开发了两个名为`Circle`和`Sphere`的类,并配有代码来查找面积和体积。 所以你的客户很高兴。 由于你的客户位于银河星系中,因此常数 Pi &lt;sup class="footnote"&gt;[ [41](#_footnotedef_41 "View footnote.") ]&lt;/sup&gt; 为 22 除以 7。因此,我们将`Pi`的值放在名为`Constants`的模块中,然后 使用语句`include Constants`包含在`Circle`和`Sphere`类中。 在下面的程序中键入并执行它。
```rb
# mixin_2.rb
......@@ -411,12 +411,12 @@ Circle Area = 154.0
Sphere Volume = 1437.333333333333
```
这样您就可以得到一些输出。 您可能会问,将常量放入模块并使用`include`语句将其混合在类中有何好处? 上面的程序教你两种道德
这样你就可以得到一些输出。 你可能会问,将常量放入模块并使用`include`语句将其混合在类中有何好处? 上面的程序教你两种道德
* 可以将常量放入模块中
* 可以将常量放入模块中
* 如果具有可以在类之间共享的通用代码 &lt;sup class="footnote"&gt;[ [42](#_footnotedef_42 "View footnote.") ]&lt;/sup&gt; ,则可以将其放入模块中并进行共享。
* 如果具有可以在类之间共享的通用代码 &lt;sup class="footnote"&gt;[ [42](#_footnotedef_42 "View footnote.") ]&lt;/sup&gt; ,则可以将其放入模块中并进行共享。
如果您在每个类中分别定义了`Pi`的值,并且您碰巧从仙女座星系中获得了 Pi 为 57 除以 18.1364 的客户端,则可以只在一个地方进行更改,即在`Constants`模块和 看到更改反映在许多类中(在我们的例子中是`Circle`和`Sphere`类)。
如果你在每个类中分别定义了`Pi`的值,并且你碰巧从仙女座星系中获得了 Pi 为 57 除以 18.1364 的客户端,则可以只在一个地方进行更改,即在`Constants`模块和 看到更改反映在许多类中(在我们的例子中是`Circle`和`Sphere`类)。
因此,道德模块有助于我们迎合超出我们银河系的客户,并且我们可以真正建立银河帝国 &lt;sup class="footnote"&gt;[ [43](#_footnotedef_43 "View footnote.") ]&lt;/sup&gt;
\ No newline at end of file
......@@ -2,14 +2,14 @@
Ruby 提供了从计算机时钟中提取时间和日期的方法。 当今所有的个人计算机都有一个称为 RTC(实时时钟)的东西,它由电池供电,即使机器关闭也可以保持时间。 许多编程语言都允许我们访问此时钟并使用日期和时间进行操作。 让我们看看如何使用 Ruby。 让我们在 irb 中执行此操作,而不是将程序写入文件中。
我们要做的第一件事是发现现在几点钟了? 为此,只需在 irb 中键入`Time.now`就可以了。 将获得当前时间。
我们要做的第一件事是发现现在几点钟了? 为此,只需在 irb 中键入`Time.now`就可以了。 将获得当前时间。
```rb
>> Time.now
=> Thu Feb 25 16:54:45 +0530 2010
```
Time.now 是`Time.new`的同义词,它创建一个新的`Time`对象。 可以使用`Time.now``Time.new`,两者将产生相同的结果。
Time.now 是`Time.new`的同义词,它创建一个新的`Time`对象。 可以使用`Time.now``Time.new`,两者将产生相同的结果。
```rb
>> Time.new
......@@ -95,7 +95,7 @@ Time.now 是`Time.new`的同义词,它创建一个新的`Time`对象。 您可
=> 2
```
`t.usec`检索时间对象中的微秒。 如果受命编写奥运会秒表应用程序,这将很有用。
`t.usec`检索时间对象中的微秒。 如果受命编写奥运会秒表应用程序,这将很有用。
```rb
>> t.usec
......@@ -109,7 +109,7 @@ Time.now 是`Time.new`的同义词,它创建一个新的`Time`对象。 您可
=> "IST"
```
有一个东西叫做 UTC 或世界时间坐标 &lt;sup class="footnote"&gt;[ [44](#_footnotedef_44 "View footnote.") ]&lt;/sup&gt; 。 经度为 0 度的时间。 `t.utc_offset`显示的时间与 UTC 的时间相差的秒数。
有一个东西叫做 UTC 或世界时间坐标 &lt;sup class="footnote"&gt;[ [44](#_footnotedef_44 "View footnote.") ]&lt;/sup&gt; 。 经度为 0 度的时间。 `t.utc_offset`显示的时间与 UTC 的时间相差的秒数。
```rb
>> t.utc_offset
......@@ -118,14 +118,14 @@ Time.now 是`Time.new`的同义词,它创建一个新的`Time`对象。 您可
从上面的示例中,我知道住在格林威治的人将在我见过 19800 秒后看到日出。
DST 表示夏令时 &lt;sup class="footnote"&gt;[ [45](#_footnotedef_45 "View footnote.") ]&lt;/sup&gt; 。 我不知道那是什么 如果的时区具有夏令时,则此函数返回`true`,否则返回`false`
DST 表示夏令时 &lt;sup class="footnote"&gt;[ [45](#_footnotedef_45 "View footnote.") ]&lt;/sup&gt; 。 我不知道那是什么 如果的时区具有夏令时,则此函数返回`true`,否则返回`false`
```rb
>> t.isdst
=> false
```
如果的时区为`UTC`,则`t.utc`返回 true 或 false
如果的时区为`UTC`,则`t.utc`返回 true 或 false
```rb
>> t.utc?
......@@ -208,7 +208,7 @@ DST 表示夏令时 &lt;sup class="footnote"&gt;[ [45](#_footnotedef_45 "View fo
### 18.2。 你住了几天?
现在,让我们看一个程序,该程序以您的生日为准,并打印出您住了多少天。 在文本编辑器中输入程序并执行
现在,让我们看一个程序,该程序以你的生日为准,并打印出你住了多少天。 在文本编辑器中输入程序并执行
```rb
#!/usr/bin/ruby
......@@ -230,7 +230,7 @@ Enter birthday (YYYY-MM-DD):2000-5-23
You have lived for 3566 days
```
好吧,这在执行该程序时可能会有所不同。 现在让我们对其进行分析。 在第一行
好吧,这在执行该程序时可能会有所不同。 现在让我们对其进行分析。 在第一行
```rb
print "Enter birthday (YYYY-MM-DD):"
......@@ -242,7 +242,7 @@ print "Enter birthday (YYYY-MM-DD):"
bday = gets.chop
```
我们获取日期并将其存储在名为`bday`的变量中。 `gets.chop`获得生日,并砍掉我们随其输入的输入符号。 因此`bday`现在保存输入的生日的字符串值。 在下一条语句中
我们获取日期并将其存储在名为`bday`的变量中。 `gets.chop`获得生日,并砍掉我们随其输入的输入符号。 因此`bday`现在保存输入的生日的字符串值。 在下一条语句中
```rb
year, month, day = bday.split('-')
......@@ -262,7 +262,7 @@ year, month, day = bday.split('-')
=> ["1994", "6", "24"]
```
如果还记得`_`(下划线)表示 irb 中最后获得的结果。 因此,分配好之后,我们现在检查`a``b``c`的值,如图所示。
如果还记得`_`(下划线)表示 irb 中最后获得的结果。 因此,分配好之后,我们现在检查`a``b``c`的值,如图所示。
```rb
>> a
......
## 19.文件
到目前为止,您已经将数据存储在程序的变量中。 当程序停止执行或计算机关闭或从内存中删除程序时,变量数据将丢失。 如果要永久存储,则必须将其存储在文件中。 当您将数据存储在文件中时,即使程序已从内存中删除,它也会保留在该文件中,并且您可以在再次运行数据时将其取回。 如果您正在计算机,kindle 或电子阅读器上阅读这本书,则该文件将永久存储在您的计算机或互联网上的其他计算机上。 在本章中,我们将看到如何使用 ruby 程序创建,操作和删除文件。
到目前为止,你已经将数据存储在程序的变量中。 当程序停止执行或计算机关闭或从内存中删除程序时,变量数据将丢失。 如果要永久存储,则必须将其存储在文件中。 当你将数据存储在文件中时,即使程序已从内存中删除,它也会保留在该文件中,并且你可以在再次运行数据时将其取回。 如果你正在计算机,kindle 或电子阅读器上阅读这本书,则该文件将永久存储在你的计算机或互联网上的其他计算机上。 在本章中,我们将看到如何使用 ruby 程序创建,操作和删除文件。
### 19.1。 将输出存储到文件中
......@@ -20,7 +20,7 @@ puts "Ruby can write into files"
$ ruby write_file.rb > something.txt
```
现在转到程序所在的工作目录,您将看到一个名为 [something.txt](code/something.txt) 的文件。 打开它,这就是您将看到的内容
现在转到程序所在的工作目录,你将看到一个名为 [something.txt](code/something.txt) 的文件。 打开它,这就是你将看到的内容
```rb
Hello World!
......@@ -46,7 +46,7 @@ puts "The file has #{readlines.length} line(s)"
$ ruby line_count.rb < something.txt
```
如果猜对了,我们给 [something.txt](code/something.txt) 作为程序的输入。 我们使用`&lt;`(小于)符号向程序指示我们正在提供文件作为输入。
如果猜对了,我们给 [something.txt](code/something.txt) 作为程序的输入。 我们使用`&lt;`(小于)符号向程序指示我们正在提供文件作为输入。
该程序在执行时提供以下结果
......@@ -122,7 +122,7 @@ end
$ ruby display_file.rb < something.txt
```
这就是将得到的输出
这就是将得到的输出
```rb
Hello World!
......@@ -177,7 +177,7 @@ Ruby can write into files
输出看起来如上图所示。 查看代码`File.new("something.txt").each { |line| puts line }`。 在代码中,我们使用`File.open`命令打开名为 [something.txt](code/something.txt) 的文件,该命令打开文件并将行存储为数组元素。 现在我们需要做的就是提取数组中的每个元素,并将其打印在控制台上,这由`.each { |line| puts line }`完成。
除了使用`File.open`,还可以使用`File.new`打开文件。 它将具有相同的结果。 编写了一个使用`File.new`的程序,如下所示,执行该程序,将获得相同的结果。
除了使用`File.open`,还可以使用`File.new`打开文件。 它将具有相同的结果。 编写了一个使用`File.new`的程序,如下所示,执行该程序,将获得相同的结果。
```rb
#!/usr/bin/ruby
......@@ -251,7 +251,7 @@ Reading file after File.open block is closed:
file_open_error.rb:8: undefined local variable or method `f' for main:Object (NameError)
```
参见突出显示的代码,我们在关闭代码块后尝试读取文件内容,并引发错误,这是因为`File.open`加载到`do` `end`代码块内的变量`f`的文件句柄中, 关闭该块后,将无法访问该文件。
参见突出显示的代码,我们在关闭代码块后尝试读取文件内容,并引发错误,这是因为`File.open`加载到`do` `end`代码块内的变量`f`的文件句柄中, 关闭该块后,将无法访问该文件。
尽管差异很小,但仍存在差异。
......@@ -287,13 +287,13 @@ is the third.
仔细查看 [line_endings.txt](code/line_endings.txt) 。 这是第一行:_ 这是第一行。_ ,这是第二行:_ 这是第二行。_
两者都在 [line_endings.txt](code/line_endings.txt) 中的同一行上,但是在执行程序时,它被打印为两条不同的行。 这是因为语句`File.open("line_endings.txt")`将文件的全部内容加载到内存中,`.each('.')`将内容分割到每个点或句点字符('。')处,并将分割后的文本的每个块放入数组中 元件。 因此,这里真正的英雄是`each`功能。 以类似的方式,可以使用任何可以定义行结尾的字符。
两者都在 [line_endings.txt](code/line_endings.txt) 中的同一行上,但是在执行程序时,它被打印为两条不同的行。 这是因为语句`File.open("line_endings.txt")`将文件的全部内容加载到内存中,`.each('.')`将内容分割到每个点或句点字符('。')处,并将分割后的文本的每个块放入数组中 元件。 因此,这里真正的英雄是`each`功能。 以类似的方式,可以使用任何可以定义行结尾的字符。
如果使用 Ruby 编写 C 编译器,则可以使用分号(;)作为行尾。
如果使用 Ruby 编写 C 编译器,则可以使用分号(;)作为行尾。
### 19.8。 逐字节读取
有时想按字节读取文件字节 &lt;sup class="footnote"&gt;[ [48](#_footnotedef_48 "View footnote.") ]&lt;/sup&gt; ,而不是阅读其中的普通英语。 到底为什么我们逐字节读取文件? 好吧,并非所有文件都包含文本。 音乐文件,视频等文件具有仅某些程序可以理解的原始数据。 如果要编写音乐或视频播放器或图像查看器,则需要读取原始数据并对其进行处理。 因此,为了读取和显示数据字节,我们使用`each_byte`函数。 看下面的代码。 输入并执行
有时想按字节读取文件字节 &lt;sup class="footnote"&gt;[ [48](#_footnotedef_48 "View footnote.") ]&lt;/sup&gt; ,而不是阅读其中的普通英语。 到底为什么我们逐字节读取文件? 好吧,并非所有文件都包含文本。 音乐文件,视频等文件具有仅某些程序可以理解的原始数据。 如果要编写音乐或视频播放器或图像查看器,则需要读取原始数据并对其进行处理。 因此,为了读取和显示数据字节,我们使用`each_byte`函数。 看下面的代码。 输入并执行
```rb
#!/usr/bin/ruby
......@@ -386,7 +386,7 @@ s
### 19.10。 重命名文件
在 Ruby 中重命名文件非常容易,您要做的就是调用 File 类中的`rename`函数。 第一个参数将是需要重命名的文件的名称,第二个参数将是新名称。 它是如此简单,您可以在 irb 上尝试一下。 看一下下面给出的程序 [named.rb](code/rename.rb) 的源代码。 在其中,我们将名为 noname.txt 的文件重命名为 somename.txt。 在运行程序之前,在工作目录上放置一个名为 noname.txt 的文件。
在 Ruby 中重命名文件非常容易,你要做的就是调用 File 类中的`rename`函数。 第一个参数将是需要重命名的文件的名称,第二个参数将是新名称。 它是如此简单,你可以在 irb 上尝试一下。 看一下下面给出的程序 [named.rb](code/rename.rb) 的源代码。 在其中,我们将名为 noname.txt 的文件重命名为 somename.txt。 在运行程序之前,在工作目录上放置一个名为 noname.txt 的文件。
```rb
#!/usr/bin/ruby
......@@ -403,7 +403,7 @@ The file noname.txt was renamed to somename.txt
### 19.11。 找出文件中的位置
您可能有时需要找出您在文件中的位置。 为此,可以使用方法`pos`。 让我们看一个示例,该示例向我们解释如何在文件中查找位置。 输入并执行 fie_position.rb
你可能有时需要找出你在文件中的位置。 为此,可以使用方法`pos`。 让我们看一个示例,该示例向我们解释如何在文件中查找位置。 输入并执行 fie_position.rb
```rb
#!/usr/bin/ruby
......@@ -439,7 +439,7 @@ After reading first line f.pos = 43
只是为了教育更多,我们使用另一个`f.gets`读取第二行,现在我们打印新文件的位置,现在我们发现指针指向位置 69。
如果想知道 [god.txt](code/god.txt) 有什么,这里是:
如果想知道 [god.txt](code/god.txt) 有什么,这里是:
```rb
All things exists because it was created.
......@@ -485,9 +485,9 @@ Now f.pos = 43
puts f.gets
```
我们正在读取`f.pos`为零的文件,也就是说,我们正在从文件的开头进行读取。 如所见,第一个`puts f.gets`的输出显示了整行`All things exists because it was created.`的输出。 请注意下一行,现在我们使用`f.pos = 12`语句将文件中的位置更改为位置 12,这意味着我们的指针从头开始是 12 个字节。 现在,在第二个 puts `f.gets`中,因为创建了输出,所以它得到了存在的输出。 这表明我们能够成功更改文件在文件中的位置。
我们正在读取`f.pos`为零的文件,也就是说,我们正在从文件的开头进行读取。 如所见,第一个`puts f.gets`的输出显示了整行`All things exists because it was created.`的输出。 请注意下一行,现在我们使用`f.pos = 12`语句将文件中的位置更改为位置 12,这意味着我们的指针从头开始是 12 个字节。 现在,在第二个 puts `f.gets`中,因为创建了输出,所以它得到了存在的输出。 这表明我们能够成功更改文件在文件中的位置。
有些人可能会认为文件位置可能为负,例如,如果您想读取文件的最后 20 个字节,则可以分配`f.pos = -20`,而在给定 f.gets 时将其打印出来。 恩,Ruby 无法做到这一点。 如果您想尝试示例(file_negative_position.rb),并查看天气,它将给出正确的结果。
有些人可能会认为文件位置可能为负,例如,如果你想读取文件的最后 20 个字节,则可以分配`f.pos = -20`,而在给定 f.gets 时将其打印出来。 恩,Ruby 无法做到这一点。 如果你想尝试示例(file_negative_position.rb),并查看天气,它将给出正确的结果。
```rb
#!/usr/bin/ruby
......@@ -523,7 +523,7 @@ END_OF_TXT
end
```
执行后,打开文件 [god.txt](code/god.txt)将在其中看到
执行后,打开文件 [god.txt](code/god.txt)将在其中看到
```rb
All things exists because it was created.
......@@ -568,7 +568,7 @@ END_OF_TXT
f.puts some_txt
```
`gets`获取文件内容,`puts`向文件中写入内容,因此我们将`some_txt`作为`puts`函数的参数传递,文件中包含的内容也将写入文件中。 程序结束,文件关闭,仅此而已。 当您打开 [god.txt](code/god.txt) 时,您会看到其中写的内容。
`gets`获取文件内容,`puts`向文件中写入内容,因此我们将`some_txt`作为`puts`函数的参数传递,文件中包含的内容也将写入文件中。 程序结束,文件关闭,仅此而已。 当你打开 [god.txt](code/god.txt) 时,你会看到其中写的内容。
### 19.13。 将内容追加到文件中
......@@ -586,7 +586,7 @@ f = File.new("log_file.txt", "a")
f.puts "\n"+Time.now.to_s+"\n"+text
```
当程序提示输入某些内容时,键入`It will be great if dinosaurs were still around`之类的内容,然后按 Enter。 几次运行后,请运行几次该程序,键入一些内容,然后再打开 [log_file.txt](code/log_file.txt) ,然后看一下其中包含的内容。 当我打开我的时,这就是我得到的:
当程序提示输入某些内容时,键入`It will be great if dinosaurs were still around`之类的内容,然后按 Enter。 几次运行后,请运行几次该程序,键入一些内容,然后再打开 [log_file.txt](code/log_file.txt) ,然后看一下其中包含的内容。 当我打开我的时,这就是我得到的:
```rb
Sat Mar 27 16:20:24 +0530 2010
......@@ -599,9 +599,9 @@ Sat Mar 27 16:21:36 +0530 2010
This is my third log. Now I'm getting bored.
```
查看的条目与时间戳的记录情况。 要了解程序如何让它遍历。
查看的条目与时间戳的记录情况。 要了解程序如何让它遍历。
第一行`puts "Enter text to append into file: "`会打印出`Enter text to append into file:`,控制会转到下一行`text = gets`,在此阶段程序等待您输入内容,然后按 Enter 键。 当您按回车键时,您输入的内容将存储在变量`text`中。
第一行`puts "Enter text to append into file: "`会打印出`Enter text to append into file:`,控制会转到下一行`text = gets`,在此阶段程序等待你输入内容,然后按 Enter 键。 当你按回车键时,你输入的内容将存储在变量`text`中。
下一行`f = File.new("log_file.txt", "a")`是我们程序的关键和重点。 在这一行中,我们以附加模式打开一个名为 [log_file.txt](code/log_file.txt) 的文件。 注意,我们将`“a”`作为第二个参数传递给`File.new`,这表明我们正在以附加模式打开它。 在这种模式下,先前存储在文件中的内容不会被删除和/或被覆盖,而是在文件末尾写入新添加的内容。
......@@ -615,7 +615,7 @@ This is my third log. Now I'm getting bored.
#### 19.14.1。 Pstore
Pstore 是二进制文件格式,几乎可以存储任何格式。 在接下来的示例中,我们将存储少量属于 Square 类的对象。 首先,我们将为 Square 写一个类,并将其放入一个名为 [square_class.rb](code/square_class.rb) 的文件中。 如果您懒惰地复制内容和下方内容并将其放入文件中,如果您是一个活跃的人/女孩,请自行输入所有内容,最后您将得到相同的结果。
Pstore 是二进制文件格式,几乎可以存储任何格式。 在接下来的示例中,我们将存储少量属于 Square 类的对象。 首先,我们将为 Square 写一个类,并将其放入一个名为 [square_class.rb](code/square_class.rb) 的文件中。 如果你懒惰地复制内容和下方内容并将其放入文件中,如果你是一个活跃的人/女孩,请自行输入所有内容,最后你将得到相同的结果。
```rb
# square_class.rb
......@@ -697,7 +697,7 @@ store[:square] << s1
store[:square] << s2
```
完成后,我们使用 end 命令关闭事务。 只需查看您的工作目录,您将能够在其中看到一个名为`my_squares`的文件,如下图所示:
完成后,我们使用 end 命令关闭事务。 只需查看你的工作目录,你将能够在其中看到一个名为`my_squares`的文件,如下图所示:
![files 46cee](img/175d9fd59021d6508c16001ed8484f90.jpg)
......@@ -736,7 +736,7 @@ Perimeter = 28
===============================
```
您所见,两个正方形的面积和周长已打印出来。 如果您觉得我在欺骗您,请使用计算器检查我们的自我。 很好地了解[中发生了什么事 pstore_write.rb](code/pstore_write.rb) 让我们遍历了代码。 在前两行
你所见,两个正方形的面积和周长已打印出来。 如果你觉得我在欺骗你,请使用计算器检查我们的自我。 很好地了解[中发生了什么事 pstore_write.rb](code/pstore_write.rb) 让我们遍历了代码。 在前两行
```rb
require 'square_class.rb'
......@@ -813,7 +813,7 @@ require 'yaml'
require 'square_class'
```
导入读取和写入 YAML 文件所需的代码。 下一个将代码加载到 [square_calss.rb](code/square_calss.rb) 中,以便可以使用正方形对象进行编程。
导入读取和写入 YAML 文件所需的代码。 下一个将代码加载到 [square_calss.rb](code/square_calss.rb) 中,以便可以使用正方形对象进行编程。
在以下几行
......
## 20\. Proc,Lambda 和块
如果您了解某些编程语言,则可能听说过闭包。 Proc 和 Blocks 是类似的事情。 您可以采用一段代码,将其粘贴在`do` `end`块之间,并将其分配给变量。 该变量包含一段代码,可以像对象一样进行操作并传递。
如果你了解某些编程语言,则可能听说过闭包。 Proc 和 Blocks 是类似的事情。 你可以采用一段代码,将其粘贴在`do` `end`块之间,并将其分配给变量。 该变量包含一段代码,可以像对象一样进行操作并传递。
Proc 就像一个函数,但是它是一个对象。 让我们看一个例子来了解什么是 Proc。 在文本编辑器中输入程序 [proc.rb](code/proc.rb) 并执行。
......@@ -31,7 +31,7 @@ say_hello = Proc.new do
end
```
在这种情况下,您将使用单个 Ruby 语句`puts “Hello World!”`,并将其放在 do 和 end 之间。 通过将`Proc.new`附加在`do`(该块的开始)之前,可以使此代码成为 Proc。 您正在将 Proc 对象分配给名为`say_hello`的变量。 现在`say_hello`可以看作是包含一个程序的东西。
在这种情况下,你将使用单个 Ruby 语句`puts “Hello World!”`,并将其放在 do 和 end 之间。 通过将`Proc.new`附加在`do`(该块的开始)之前,可以使此代码成为 Proc。 你正在将 Proc 对象分配给名为`say_hello`的变量。 现在`say_hello`可以看作是包含一个程序的东西。
现在如何调用或执行代码? 当我们需要调用名为`say_hello`的 Proc 片段时,我们编写以下命令
......@@ -43,7 +43,7 @@ say_hello.call
### 20.1。 传递参数
像函数一样,可以将参数传递给 Proc。 要查看其工作方式,请键入程序 [proc_hello_you.rb](code/proc_hello_you.rb) 并执行它。
像函数一样,可以将参数传递给 Proc。 要查看其工作方式,请键入程序 [proc_hello_you.rb](code/proc_hello_you.rb) 并执行它。
```rb
#!/usr/bin/ruby
......@@ -119,7 +119,7 @@ def execute_proc some_proc
end
```
我们接受一个称为`some_proc`的参数,我们将其假定为 Proc。 然后,我们使用其自己的`call`方法执行该函数,即在函数中,我们仅使用`some_proc.call`对其进行调用,以执行传递的 Proc。 如果看一下接下来的几行,我们将创建一个名为`say_hello`的 Proc
我们接受一个称为`some_proc`的参数,我们将其假定为 Proc。 然后,我们使用其自己的`call`方法执行该函数,即在函数中,我们仅使用`some_proc.call`对其进行调用,以执行传递的 Proc。 如果看一下接下来的几行,我们将创建一个名为`say_hello`的 Proc
```rb
say_hello = Proc.new do
......@@ -267,7 +267,7 @@ Output
### 20.6。 具有函数的 Proc 和 Lambda
好的,Proc 和 Lambda 有什么区别。 它们之间有两个主要区别,这是第一个。 在下面的示例[中,calling_proc_and_lambda_in_function.rb](code/calling_proc_and_lambda_in_function.rb) 我们具有两个函数,即`calling_lambda`和`calling_proc`,请在的计算机上键入并运行此文件
好的,Proc 和 Lambda 有什么区别。 它们之间有两个主要区别,这是第一个。 在下面的示例[中,calling_proc_and_lambda_in_function.rb](code/calling_proc_and_lambda_in_function.rb) 我们具有两个函数,即`calling_lambda`和`calling_proc`,请在的计算机上键入并运行此文件
```rb
# calling_proc_and_lambda_in_function.rb
......@@ -299,7 +299,7 @@ Finished calling_lambda function
Started calling_proc
```
将看到如上所示的输出。 因此,让我们继续执行它。 首先调用`calling_lambda`功能时,程序将通过执行`puts "Started calling_lambda"`打印`Started calling_lambda`。 接下来,我们定义一个新的 lambda `some_lambda`,并使用以下几行代码进行调用
将看到如上所示的输出。 因此,让我们继续执行它。 首先调用`calling_lambda`功能时,程序将通过执行`puts "Started calling_lambda"`打印`Started calling_lambda`。 接下来,我们定义一个新的 lambda `some_lambda`,并使用以下几行代码进行调用
```rb
some_lambda = lambda{ return "In Lambda" }
......@@ -337,7 +337,7 @@ ArgumentError: wrong number of arguments (0 for 1)
from /home//karthikeyan.ak/.rvm/rubies/ruby-2.1.3/bin/irb:11:in `<main>'
```
我已经使用 irb 来演示该示例。 在上面的代码中,我们在以下语句`lambda = -&gt; (x) { x.to_s }`中定义了一个 Lambda,现在我们可以使用以下语句 lambda.call 对其进行调用,如所见,因为我们有一个参数`x`,并且没有传递任何内容给 Lambda 引发异常并对此进行抱怨。 现在让我们尝试一下
我已经使用 irb 来演示该示例。 在上面的代码中,我们在以下语句`lambda = -&gt; (x) { x.to_s }`中定义了一个 Lambda,现在我们可以使用以下语句 lambda.call 对其进行调用,如所见,因为我们有一个参数`x`,并且没有传递任何内容给 Lambda 引发异常并对此进行抱怨。 现在让我们尝试一下
```rb
>> proc = Proc.new { |x| x.to_s}
......@@ -346,7 +346,7 @@ ArgumentError: wrong number of arguments (0 for 1)
=> ""
```
因此,如在上面看到的那样,是否应将参数传递给 Proc,如果不传递参数,则在不提供参数的情况下调用 Proc,Proc 不会抱怨,而是将其视为`nil`。 &lt;sup class="footnote"&gt;[ [49](#_footnotedef_49 "View footnote.") ]&lt;/sup&gt;
因此,如在上面看到的那样,是否应将参数传递给 Proc,如果不传递参数,则在不提供参数的情况下调用 Proc,Proc 不会抱怨,而是将其视为`nil`。 &lt;sup class="footnote"&gt;[ [49](#_footnotedef_49 "View footnote.") ]&lt;/sup&gt;
### 20.8。 Lambda 和数组
......@@ -400,7 +400,7 @@ Output
boom thata
```
现在让我们看一下代码。 在代码中,我们在以下行`def some_method *args, &block`中定义了一个名为`some_method`的方法。 请注意,我们正在接受`*args`中的所有参数,并且有一个名为`&block`的新名称将被包含在代码块中。 您可以将&块替换为其他变量,例如`&a`或`&something`或任何您喜欢的变量。
现在让我们看一下代码。 在代码中,我们在以下行`def some_method *args, &block`中定义了一个名为`some_method`的方法。 请注意,我们正在接受`*args`中的所有参数,并且有一个名为`&block`的新名称将被包含在代码块中。 你可以将&块替换为其他变量,例如`&a`或`&something`或任何你喜欢的变量。
现在,忘记功能主体中的内容。 现在让我们看一下函数的调用,如下所示
......@@ -410,7 +410,7 @@ some_method 1, 3, 5, 7 do
end
```
因此,我们调用`some_method`并传递参数`1, 3, 5, 7`。 这将以数组形式存储在`*args` &lt;sup class="footnote"&gt;[ [50](#_footnotedef_50 "View footnote.") ]&lt;/sup&gt; 变量中。 现在看到以`do`开头和以`end`结尾,在这两者之间,可以具有任意数量的语句,换句话说,它是一个代码块。 我们只有一个声明`puts "boom thata"`,就是这样。 此代码块将放入`&block`变量。 现在在 some_method 中注意以下语句
因此,我们调用`some_method`并传递参数`1, 3, 5, 7`。 这将以数组形式存储在`*args` &lt;sup class="footnote"&gt;[ [50](#_footnotedef_50 "View footnote.") ]&lt;/sup&gt; 变量中。 现在看到以`do`开头和以`end`结尾,在这两者之间,可以具有任意数量的语句,换句话说,它是一个代码块。 我们只有一个声明`puts "boom thata"`,就是这样。 此代码块将放入`&block`变量。 现在在 some_method 中注意以下语句
```rb
def some_method *args, &block
......
## 21.多线程
通常,程序是逐行读取的,并由计算机逐步执行。 在任何给定的时间点,计算机仅执行一条指令 1。 随着技术的进步,可以同时执行许多指令,这种同时执行许多操作的过程称为多处理或并行处理。 想象一下,您要吃 5 个披萨。 您需要花费很长时间。 如果您也可以带来您的朋友,那么您的人们可以分担负担。 如果您可以组成一个由 20 个人组成的小组,那么吃 5 个披萨就变得像吃零食一样容易。 完成分配任务所需的时间大大减少。
通常,程序是逐行读取的,并由计算机逐步执行。 在任何给定的时间点,计算机仅执行一条指令 1。 随着技术的进步,可以同时执行许多指令,这种同时执行许多操作的过程称为多处理或并行处理。 想象一下,你要吃 5 个披萨。 你需要花费很长时间。 如果你也可以带来你的朋友,那么你的人们可以分担负担。 如果你可以组成一个由 20 个人组成的小组,那么吃 5 个披萨就变得像吃零食一样容易。 完成分配任务所需的时间大大减少。
在 Ruby 编程中,可以使解释器以并行方式执行代码。 并行执行代码的过程称为多线程。 要显示多线程的工作方式,请在文本编辑器中键入以下程序并执行。
在 Ruby 编程中,可以使解释器以并行方式执行代码。 并行执行代码的过程称为多线程。 要显示多线程的工作方式,请在文本编辑器中键入以下程序并执行。
```rb
#!/usr/bin/ruby
......@@ -169,7 +169,7 @@ Before thread variable = 0
After thread variable = 5
```
输入程序并运行。 它将产生上面显示的结果。 从程序中可以看到,在创建线程之前,我们将名为`variable`的变量初始化为 0。 在线程内部,我们将`variable`的值更改为 5。在线程块之后,我们输出的变量值现在为 5。该程序向我们展示了可以访问和操作在主线程中声明的变量。
输入程序并运行。 它将产生上面显示的结果。 从程序中可以看到,在创建线程之前,我们将名为`variable`的变量初始化为 0。 在线程内部,我们将`variable`的值更改为 5。在线程块之后,我们输出的变量值现在为 5。该程序向我们展示了可以访问和操作在主线程中声明的变量。
现在让我们看看是否可以在线程范围之外访问在线程内部创建的变量? 键入以下程序( [thread_variables_1.rb](code/thread_variables_1.rb) )并执行
......@@ -206,7 +206,7 @@ thread_variables_1.rb:13: undefined local variable or method `thread_variable' f
puts "thread_variable = #{thread_variable}"
```
所见,该程序/ Ruby 解释器吐出错误的输出如下所示:
所见,该程序/ Ruby 解释器吐出错误的输出如下所示:
```rb
thread_variables_1.rb:13: undefined local variable or method `thread_variable' for main:Object (NameError)
......@@ -216,7 +216,7 @@ thread_variables_1.rb:13: undefined local variable or method `thread_variable' f
### 21.2。 线程排除
假设有两个共享同一资源的线程,则将该资源作为变量。 假设第一个线程修改了变量,而第二个线程尝试访问变量时,会发生什么呢? 答案很简单明了,尽管程序运行似乎没有错误,但可能无法获得理想的结果。 这个概念很难理解,让我尝试用一​​个例子来解释它。 输入并执行 [thread_exclusion.rb](code/thread_exclusion.rb)
假设有两个共享同一资源的线程,则将该资源作为变量。 假设第一个线程修改了变量,而第二个线程尝试访问变量时,会发生什么呢? 答案很简单明了,尽管程序运行似乎没有错误,但可能无法获得理想的结果。 这个概念很难理解,让我尝试用一​​个例子来解释它。 输入并执行 [thread_exclusion.rb](code/thread_exclusion.rb)
```rb
#!/usr/bin/ruby
......@@ -253,7 +253,7 @@ difference = 127524
puts "difference = #{diff}"
```
人们会期望该值为零,但我们得到的值为 127524,在的计算机中,该值可能会有所不同,因为它取决于机器速度,运行的处理器和其他参数。 但是道德是`diff`应该为零有一定价值,为什么呢?
人们会期望该值为零,但我们得到的值为 127524,在的计算机中,该值可能会有所不同,因为它取决于机器速度,运行的处理器和其他参数。 但是道德是`diff`应该为零有一定价值,为什么呢?
我们在第一个循环中看到`x`递增,然后`y`递增,假设`x`的值为 5,y 值为 4,即`x`刚在语句中递增 `x += 1`,现在 Ruby 解释器将要读取并执行`y += 1`,这将使`y`从 4 变为 5。在此阶段,第二个线程由计算机执行。 所以在声明中
......@@ -340,9 +340,9 @@ Thread.new {
### 21.3。 死锁
您是否曾经站在队列中,或等待过什么。 我们都在机场等了一个地方,以便对我们的行李进行扫描和清理。 可以说行李扫描机出故障了,您被困在机场。 预计您将参加重要的公司会议,并且有重要的演讲,并且您必须发表重要的讲话。 由于行李扫描仪发生故障,因此您所需要的资源不可用,并且您掌握了在会议中进行交谈的关键知识,因此会议忙得不可开交。 会议中的一个可能会答应带他的家人去看电影,他可能会在延迟的会议之后回来很晚,因此一切都搞砸了。
你是否曾经站在队列中,或等待过什么。 我们都在机场等了一个地方,以便对我们的行李进行扫描和清理。 可以说行李扫描机出故障了,你被困在机场。 预计你将参加重要的公司会议,并且有重要的演讲,并且你必须发表重要的讲话。 由于行李扫描仪发生故障,因此你所需要的资源不可用,并且你掌握了在会议中进行交谈的关键知识,因此会议忙得不可开交。 会议中的一个可能会答应带他的家人去看电影,他可能会在延迟的会议之后回来很晚,因此一切都搞砸了。
想象一下,行李扫描仪,您,一个必须听见您的会议的人,是 Ruby 程序的线程。 由于行李扫描仪不会释放资源(您的行李),因此您的流程将被延迟,并且由于延迟,许多其他依赖于您的流程也会延迟。 这种情况称为死锁。 它也发生在 Ruby 程序中。 每当出现这种情况时,人们就会等待而不是向前冲。 您等待行李被放行,公司等待您的到来,芒家族等待他将其带到电影中。 如果不等人们赶时间,就会造成混乱。 Ruby 具有避免这种混乱并处理这种死锁的机制。 我们使用一种称为条件变量的东西。 看下面的程序( [thread_condition_variable.rb](code/thread_condition_variable.rb) ),键入并执行它。
想象一下,行李扫描仪,你,一个必须听见你的会议的人,是 Ruby 程序的线程。 由于行李扫描仪不会释放资源(你的行李),因此你的流程将被延迟,并且由于延迟,许多其他依赖于你的流程也会延迟。 这种情况称为死锁。 它也发生在 Ruby 程序中。 每当出现这种情况时,人们就会等待而不是向前冲。 你等待行李被放行,公司等待你的到来,芒家族等待他将其带到电影中。 如果不等人们赶时间,就会造成混乱。 Ruby 具有避免这种混乱并处理这种死锁的机制。 我们使用一种称为条件变量的东西。 看下面的程序( [thread_condition_variable.rb](code/thread_condition_variable.rb) ),键入并执行它。
```rb
#!/usr/bin/ruby
......@@ -402,9 +402,9 @@ puts "Thread b is using a resource needed by a, once its done it will signal to
### 21.4。 创建多个线程
假设您有一种情况,必须创建许多线程,并且必须以优雅的方式完成,说一种情况可能会出现,您甚至不知道可以创建多少个线程,但是必须创建它们并且 程序应该等待他们加入然后退出,所以让我们看看如何编写代码。
假设你有一种情况,必须创建许多线程,并且必须以优雅的方式完成,说一种情况可能会出现,你甚至不知道可以创建多少个线程,但是必须创建它们并且 程序应该等待他们加入然后退出,所以让我们看看如何编写代码。
因此,在的文本编辑器中键入以下程序并运行它
因此,在的文本编辑器中键入以下程序并运行它
```rb
# many_threads.rb
......@@ -437,7 +437,7 @@ Hi
Hi
```
如果您没有获得如上所述的确切输出,请不要担心,因为程序中存在一些随机性。 让我解释一下该程序,以便您看清楚它。
如果你没有获得如上所述的确切输出,请不要担心,因为程序中存在一些随机性。 让我解释一下该程序,以便你看清楚它。
首先,我们声明一个将容纳线程的数组,如下所示
......@@ -593,7 +593,7 @@ thread_exception_true.rb:8:in `/': divided by 0 (ZeroDivisionError)
from thread_exception_true.rb:4
```
注意,在程序中我们创建了一个名为`t`的线程,如果很安静,则程序中没有`t.join`。 与其等待线程加入,不如等待足够长的时间来完成线程。 为了使线程完成,我们使用语句`sleep(10)`等待 10 秒。
注意,在程序中我们创建了一个名为`t`的线程,如果很安静,则程序中没有`t.join`。 与其等待线程加入,不如等待足够长的时间来完成线程。 为了使线程完成,我们使用语句`sleep(10)`等待 10 秒。
注意我们设置的`t.abort_on_exception = true`行,如果线程`t`中引发异常,则程序必须中止。 现在让我们分析线程`t`中的内容。 线程`t`包含以下代码
......@@ -651,11 +651,11 @@ Program completed
从输出中可以看到,没有异常发生的痕迹 4。 执行线程`t`之后的代码,我们得到显示为`Program Completed`的输出。 这是因为我们将`abort_on_exception`设置为`false`。
可以从最后两个程序中看到我们尚未使用`t.join`,相反,我们已经等待了足够长的时间以终止线程。 之所以这样,是因为一旦我们将线程(导致)与父线程(在这种情况下为主线程)连接在一起,子线程中出现的异常就会传播到父线程/等待线程,因此`abort_on_exception`甚至没有作用 设置为 false。 因此,每当异常发生时,它就会反映在我们的终端上。
可以从最后两个程序中看到我们尚未使用`t.join`,相反,我们已经等待了足够长的时间以终止线程。 之所以这样,是因为一旦我们将线程(导致)与父线程(在这种情况下为主线程)连接在一起,子线程中出现的异常就会传播到父线程/等待线程,因此`abort_on_exception`甚至没有作用 设置为 false。 因此,每当异常发生时,它就会反映在我们的终端上。
### 21.6。 线程类方法
您可以使用某些线程方法来操纵线程的属性。 这些在下面列出。 如果您一点都不懂,那就不用担心。
你可以使用某些线程方法来操纵线程的属性。 这些在下面列出。 如果你一点都不懂,那就不用担心。
<colgroup><col style="width: 33.3333%;"> <col style="width: 33.3333%;"> <col style="width: 33.3334%;"></colgroup>
| 斯诺 | 方法 | 它能做什么 |
......
......@@ -17,7 +17,7 @@ division_exception.rb:3:in `/': divided by 0 (ZeroDivisionError)
from division_exception.rb:3:in `<main>'
```
您所见,您将获得一个异常作为输出。 看到常数`ZeroDivisionError`。 我们将在几个示例中看到的使用。 因此,当 Ruby 解释器注意到它无法处理某些内容时,就会引发异常。
你所见,你将获得一个异常作为输出。 看到常数`ZeroDivisionError`。 我们将在几个示例中看到的使用。 因此,当 Ruby 解释器注意到它无法处理某些内容时,就会引发异常。
如果我们把例外扔给已经为开发一个程序付出了数百万美元的客户的客户,那将不是什么好事。 我们宁愿尝试提供他们可以理解的内容。 因此,在下面显示的示例 [code / rescue.rb](code/rescue.rb) 中,我们看到了如何处理此异常。 在文本编辑器中键入以下程序并运行它
......@@ -37,7 +37,7 @@ Output
We are unable to proceed due to unavoidable reasons :(
```
正如您看到的那样,您看到的不是友好的`ZeroDivisionError`输出,而是一条友好的消息,指出由于不可避免的原因其无法继续进行。 诀窍是,如果您认为在`begin``end`块周围的代码中可能会发生某些异常,如下所示
正如你看到的那样,你看到的不是友好的`ZeroDivisionError`输出,而是一条友好的消息,指出由于不可避免的原因其无法继续进行。 诀窍是,如果你认为在`begin``end`块周围的代码中可能会发生某些异常,如下所示
```rb
begin
......@@ -55,7 +55,7 @@ begin
end
```
发生异常时,`rescue`下面的代码开始执行。 而已! 好了,现在如何粗略地处理异常。
发生异常时,`rescue`下面的代码开始执行。 而已! 好了,现在如何粗略地处理异常。
现在让我们看一种捕获或从异常中解脱出来的改进方法。 参见下面的代码 [rescue_1.rb](code/rescue_1.rb) ,键入并执行
......@@ -75,7 +75,7 @@ Output
Oh nooo! boom thata has cursed us!!!!!
```
您会看到 Boom Thata(众神)诅咒的输出。 不必为此担心,Boom Thata 是我的朋友,并且会和他交谈以扭转局势。 在这里,我们将类似`rescue ZeroDivisionError`的代码放入其中,告诉它如果仅发生零除法错误,则可以进行挽救。 如果发生其他异常,由于我们仅处理`ZeroDivisionError`,您将不会因此而被救出。
你会看到 Boom Thata(众神)诅咒的输出。 不必为此担心,Boom Thata 是我的朋友,并且会和他交谈以扭转局势。 在这里,我们将类似`rescue ZeroDivisionError`的代码放入其中,告诉它如果仅发生零除法错误,则可以进行挽救。 如果发生其他异常,由于我们仅处理`ZeroDivisionError`,你将不会因此而被救出。
为了显示我的意思,请在下面键入程序( [rescue_2.rb](code/rescue_2.rb) )并执行它
......@@ -97,9 +97,9 @@ Traceback (most recent call last):
rescue_2.rb:4:in `*': no implicit conversion of String into Integer (TypeError)
```
在这里,我们仍然在终端上出现错误,因为将两个字符串相乘会产生一个不同的错误,称为`TypeError`,如在输出中看到的,而不是`ZeroDivisionError`。 并且在程序中,我们仅针对`ZerodivisionError`进行了救援。
在这里,我们仍然在终端上出现错误,因为将两个字符串相乘会产生一个不同的错误,称为`TypeError`,如在输出中看到的,而不是`ZeroDivisionError`。 并且在程序中,我们仅针对`ZerodivisionError`进行了救援。
假设您要打印出异常。 出于调试目的或其他目的。 那么该怎么做。 以下程序向您展示了这一点。 键入程序 printing_exception.rb 并运行它
假设你要打印出异常。 出于调试目的或其他目的。 那么该怎么做。 以下程序向你展示了这一点。 键入程序 printing_exception.rb 并运行它
```rb
# printing_exception.rb
......@@ -119,9 +119,9 @@ The following exception has occured:
#<ZeroDivisionError: divided by 0>
```
您所见,您可以打印一个异常。 只要注意`p e`行,它就是我们在其中打印异常的地方。 `e`是例外对象,`p`是看跌期权的简称。 希望您注意到此代码`rescue ⇒ e`将异常推送到变量`e`中。 `e`就是这种例外。
你所见,你可以打印一个异常。 只要注意`p e`行,它就是我们在其中打印异常的地方。 `e`是例外对象,`p`是看跌期权的简称。 希望你注意到此代码`rescue ⇒ e`将异常推送到变量`e`中。 `e`就是这种例外。
在下一个示例中,我们将看到如何追溯异常。 例外情况是,在现实世界中抛出的程序可能会被埋在多个层次中。 为了找到答案,最好需要追溯它。 在文本编辑器中键入以下程序,然后运行它。
在下一个示例中,我们将看到如何追溯异常。 例外情况是,在现实世界中抛出的程序可能会被埋在多个层次中。 为了找到答案,最好需要追溯它。 在文本编辑器中键入以下程序,然后运行它。
```rb
# backtracing_exception.rb
......@@ -139,9 +139,9 @@ Output
["backtracing_exception.rb:4:in `/'", "backtracing_exception.rb:4:in `<main>'"]
```
我们正在使用`p e.backtrace`打印反向跟踪。 如果可以注意到输出,则表明第 4 行发生了异常。如果在文本编辑器中显示了行号,则可以立即识别该行并进行调试。
我们正在使用`p e.backtrace`打印反向跟踪。 如果可以注意到输出,则表明第 4 行发生了异常。如果在文本编辑器中显示了行号,则可以立即识别该行并进行调试。
接下来(第二部分输出)表示 main 中发生了异常。 您可能想知道什么是主要的? 它在您的文本编辑器中首先运行的程序称为 main。
接下来(第二部分输出)表示 main 中发生了异常。 你可能想知道什么是主要的? 它在你的文本编辑器中首先运行的程序称为 main。
### 22.1 异常和线程
......@@ -177,7 +177,7 @@ thread_exception_true.rb:8:in `/': divided by 0 (ZeroDivisionError)
from thread_exception_true.rb:8:in `block in <main>'
```
您所见,程序抛出`ZeroDivisionError`异常,当`i`的值变为零且需要除以 25 时,会在`while`循环中发生这种情况。 注意`t.abort_on_exception = true`行,这里我们告诉程序在出现异常时中止或停止。 如果所有其他线程并行运行,这将停止所有其他线程。 假设您有一个多线程程序,其中必须所有线程都必须无例外地运行,并且线程之间是相互依赖的,那么最好以这样的方式编写代码:当异常发生时程序中止 在其中一根线中凸起。
你所见,程序抛出`ZeroDivisionError`异常,当`i`的值变为零且需要除以 25 时,会在`while`循环中发生这种情况。 注意`t.abort_on_exception = true`行,这里我们告诉程序在出现异常时中止或停止。 如果所有其他线程并行运行,这将停止所有其他线程。 假设你有一个多线程程序,其中必须所有线程都必须无例外地运行,并且线程之间是相互依赖的,那么最好以这样的方式编写代码:当异常发生时程序中止 在其中一根线中凸起。
可以说,我们编写的程序可以忽略线程上的异常,而其他线程可以轻松运行,然后在 [thread_exception_false.rb](code/thread_exception_false.rb) 下看到程序中的`t.abort_on_exception = false`行。 在这里,我们指定`t.abort_on_exception = false`,以便程序运行,当发生异常时,特定线程停止运行,而其他线程继续运行,好像什么也没发生。
......@@ -230,7 +230,7 @@ Enter a number 1 - 10:
raise.rb:5:in `<main>': You did not enter right num (RuntimeError)
```
从输出中可以看到,如果输入的任何数字不是从 1 到 10,程序都会引发异常。请参见代码段`raise "You did not enter right num"`,这就是在 Ruby 中引发异常的全部过程。 关键字`raise`后跟一个对象,在这种情况下,我们给出了一个字符串,但是如果我们给出一个常量(引发异常的规范),那将是很好的。 [raise_1.rb](code/raise_1.rb) 下面的程序显示了如何处理自己的异常,该异常与先前编写的救援程序没有什么不同。
从输出中可以看到,如果输入的任何数字不是从 1 到 10,程序都会引发异常。请参见代码段`raise "You did not enter right num"`,这就是在 Ruby 中引发异常的全部过程。 关键字`raise`后跟一个对象,在这种情况下,我们给出了一个字符串,但是如果我们给出一个常量(引发异常的规范),那将是很好的。 [raise_1.rb](code/raise_1.rb) 下面的程序显示了如何处理自己的异常,该异常与先前编写的救援程序没有什么不同。
```rb
# raise_1.rb
......
此差异已折叠。
此差异已折叠。
......@@ -4,7 +4,7 @@
### 25.1。 发送
Ruby 有一个功能强大的方法`send`。 也就是说,如果对象`p`具有方法`name`,则在 ruby 中我们可以使用`p.name`对其进行调用,或者还有另一种方法来调用它。 我们用`p.send(:name)``p.send("name")`称呼它。 那么,这有什么用? 这样做的用途是,可以从用户输入或收到的其他输入中确定要调用的函数。
Ruby 有一个功能强大的方法`send`。 也就是说,如果对象`p`具有方法`name`,则在 ruby 中我们可以使用`p.name`对其进行调用,或者还有另一种方法来调用它。 我们用`p.send(:name)``p.send("name")`称呼它。 那么,这有什么用? 这样做的用途是,可以从用户输入或收到的其他输入中确定要调用的函数。
让我们看一个基本的例子。 在文本编辑器中键入以下程序 [send.rb](code/send.rb) 并运行它。
......@@ -28,7 +28,7 @@ puts p.send(:speak)
Hello I am Karthik
```
好的,正如您在突出显示的代码 p.send(:spe​​ak)中所看到的那样,我们正在使用 send 方法调用 Person 类的实例 p 的语音功能。 现在就发送。 兴奋起来!!! 告知您正在学习元编程,并开始向同事吹牛。
好的,正如你在突出显示的代码 p.send(:spe​​ak)中所看到的那样,我们正在使用 send 方法调用 Person 类的实例 p 的语音功能。 现在就发送。 兴奋起来!!! 告知你正在学习元编程,并开始向同事吹牛。
好吧,希望你吹牛。 现在让我们来看一下`send`函数的一些更实际的例子。 输入示例 [send_1.rb](code/send_1.rb) 并执行
......@@ -76,7 +76,7 @@ puts "The mark in #{subject} is #{s.send(subject)}"
### 25.2。 方法缺失
假设有一个仅包含某些方法的类,并且如果程序员调用了其他疯狂的方法,并且想要捕获它并查看它是否仍然可以使用,则可以使用`method_missing`方法捕获该方法 和其他东西。
假设有一个仅包含某些方法的类,并且如果程序员调用了其他疯狂的方法,并且想要捕获它并查看它是否仍然可以使用,则可以使用`method_missing`方法捕获该方法 和其他东西。
让我们看一下有关方法缺失的程序。 在测试编辑器中键入程序 [method_missing.rb](code/method_missing.rb) 并执行
......@@ -111,9 +111,9 @@ in block
in block
```
让我们看看该程序的工作原理,在`s = Something.new`行中,我们创建了`Something`类的新实例变量`s`。 然后在下一行中执行`s.call_method "boo", 5`,在此行中,我们在`s`上调用一个名为`call_method`的方法,如果查看类`Something`会注意到在其中没有称为 call_method 的方法或函数 它,但程序不会抛出错误,异常或其他任何信息。
让我们看看该程序的工作原理,在`s = Something.new`行中,我们创建了`Something`类的新实例变量`s`。 然后在下一行中执行`s.call_method "boo", 5`,在此行中,我们在`s`上调用一个名为`call_method`的方法,如果查看类`Something`会注意到在其中没有称为 call_method 的方法或函数 它,但程序不会抛出错误,异常或其他任何信息。
好吧,发生了什么事? 如果您注意到 Something 类,您将看到一个名为 method_missing 的方法,该方法已实现,如下所示
好吧,发生了什么事? 如果你注意到 Something 类,你将看到一个名为 method_missing 的方法,该方法已实现,如下所示
```rb
def method_missing method, *args, &block
......@@ -123,7 +123,7 @@ def method_missing method, *args, &block
end
```
此方法接受三个参数,在我们的代码中,我们已将这些参数命名为`method``*args``&block`。 该方法接受方法名称,该名称是在对象`s`上调用的方法的名称,`*args`具有传递给该方法的属性,在本例中,其`call_method`和传递的属性为`“boo”``5``&block`接受已传递的任何块。 如果看到下面的`s`,我们将其称为`call_method`
此方法接受三个参数,在我们的代码中,我们已将这些参数命名为`method``*args``&block`。 该方法接受方法名称,该名称是在对象`s`上调用的方法的名称,`*args`具有传递给该方法的属性,在本例中,其`call_method`和传递的属性为`“boo”``5``&block`接受已传递的任何块。 如果看到下面的`s`,我们将其称为`call_method`
```rb
s.call_method "boo", 5 do |x|
......@@ -172,9 +172,9 @@ def method_missing method_name
end
```
在方法中缺少方法。 看一下代码,在`method_name.to_s.match(/get_(\w+)/)`这一行中,我们提取与`get_`关联的任何方法,然后在此语句中将提取的术语称为`eval("self.#{$1}")`。 如果无法理解这些内容,则可能必须阅读[正则表达式](#_regular_expressions)一章。
在方法中缺少方法。 看一下代码,在`method_name.to_s.match(/get_(\w+)/)`这一行中,我们提取与`get_`关联的任何方法,然后在此语句中将提取的术语称为`eval("self.#{$1}")`。 如果无法理解这些内容,则可能必须阅读[正则表达式](#_regular_expressions)一章。
现在如何实际使用它,例如,您可以拥有一个`get_db_&lt;method name&gt;`,您可以在其中从数据库中获取值,或者说`store_db_&lt;method name&gt;(values…​.)`,您可以在其中捕获它并将其存储在数据库中。
现在如何实际使用它,例如,你可以拥有一个`get_db_&lt;method name&gt;`,你可以在其中从数据库中获取值,或者说`store_db_&lt;method name&gt;(values…​.)`,你可以在其中捕获它并将其存储在数据库中。
### 25.3。 定义方法
......@@ -199,7 +199,7 @@ Output
25
```
好的,所以输出为 25。 如果您注意到程序 [define_method.rb](code/define_method.rb) ,您会注意到,在上面的几行中,我们正在使用此尴尬的语句定义名为 area 的方法,如下所示
好的,所以输出为 25。 如果你注意到程序 [define_method.rb](code/define_method.rb) ,你会注意到,在上面的几行中,我们正在使用此尴尬的语句定义名为 area 的方法,如下所示
```rb
define_method :area do |side|
......@@ -207,7 +207,7 @@ define_method :area do |side|
end
```
可能会想到为什么我们不这样做:
可能会想到为什么我们不这样做:
```rb
def area side
......@@ -240,7 +240,7 @@ Output
Zigor has written a book named I Love Ruby
```
因此,在上面的程序中,我们有两个突出显示的部分,第一个是`Book_hash = {author: "Zigor", title: "I Love Ruby", page: 95}`,在这里是分配给哈希值的常量。 在现实世界中,它可能是一个从文件动态加载一些哈希值的变量。 在课堂书中,会看到以下几行:
因此,在上面的程序中,我们有两个突出显示的部分,第一个是`Book_hash = {author: "Zigor", title: "I Love Ruby", page: 95}`,在这里是分配给哈希值的常量。 在现实世界中,它可能是一个从文件动态加载一些哈希值的变量。 在课堂书中,会看到以下几行:
```rb
Book_hash.each do |key, value|
......@@ -256,7 +256,7 @@ end
### 25.4。 等级评估
假设您有一个实例对象,您想在其类中添加一些内容,可以使用一种名为`class_eval`的方法,下面举一个例子。 在文本编辑器中键入以下程序并执行。
假设你有一个实例对象,你想在其类中添加一些内容,可以使用一种名为`class_eval`的方法,下面举一个例子。 在文本编辑器中键入以下程序并执行。
```rb
# class_eval.rb
......@@ -282,7 +282,7 @@ Output
I am a dog
```
查看下面显示的代码。 因此,具有变量`dog`,它是`Animal`的实例。 可以说,在程序中突然我们决定在`dog`的类中添加`say_something`的方法,即`Animal`,我们要做的就是在`class_eval`块中编写该方法,如下所示
查看下面显示的代码。 因此,具有变量`dog`,它是`Animal`的实例。 可以说,在程序中突然我们决定在`dog`的类中添加`say_something`的方法,即`Animal`,我们要做的就是在`class_eval`块中编写该方法,如下所示
```rb
dog.class.class_eval do
......
## 26.基准
基准是一种度量。 您可以测量代码运行所需的时间。 所以,为什么这么重要? 随着您成为更认真的编码人员,完成一件工作就不再重要了。 重要的是您编写代码的程度以及代码在实时环境中的性能。 您必须知道编写快速运行的代码。 要检查您的代码片段是否比其他代码片段更快,可以使用基准测试。
基准是一种度量。 你可以测量代码运行所需的时间。 所以,为什么这么重要? 随着你成为更认真的编码人员,完成一件工作就不再重要了。 重要的是你编写代码的程度以及代码在实时环境中的性能。 你必须知道编写快速运行的代码。 要检查你的代码片段是否比其他代码片段更快,可以使用基准测试。
以下面的示例为例,输入并运行
......@@ -30,7 +30,7 @@ end
<< 0.160000 0.000000 0.160000 ( 0.168452)
```
因此,让我遍历代码,在`require 'benchmark'`行中,基准测试库作为 Ruby 标准发行版的一部分包含在内,因此可以要求此代码在文件中不必大惊小怪。
因此,让我遍历代码,在`require 'benchmark'`行中,基准测试库作为 Ruby 标准发行版的一部分包含在内,因此可以要求此代码在文件中不必大惊小怪。
现在让我们看一下这个块
......@@ -59,7 +59,7 @@ end
参见上面的代码。 我们正在使用`b.report("+= ")`准备报告,可以将将在输出中打印的任何字符串传递给报告函数。 如果查看输出的第二行`+= 55.030000 7.320000 62.350000 ( 62.303848)`,则会打印`+=`,因为`“+=”`已传递到`b.report()`
`b.report()``打开一个代码块,可以将任何需要基准标记的内容传递给该代码块。 在这里,我们传递了如下所示的代码片段
`b.report()``打开一个代码块,可以将任何需要基准标记的内容传递给该代码块。 在这里,我们传递了如下所示的代码片段
```rb
b.report("+= ") do
......@@ -94,7 +94,7 @@ end
因此,使用`&lt;&lt;`仅需 0.1685 秒,因此在字符串连接方面,`&lt;&lt;`远优于`+=`。
现在,让我们看看其他内容。 你们都知道计算机有内存。 当程序运行时,它需要记住事情并消耗一些内存,有时当可用内存变少时,Ruby 解释器将清理内存。 这称为垃圾收集 &lt;sup class="footnote"&gt;[ [62](#_footnotedef_62 "View footnote.") ]&lt;/sup&gt; 。 就像您的城市或市政当局收集垃圾一样,城市运行正常。 现在想想,如果不收集垃圾,而您遇到的垃圾会流到街道上,整个城市步履蹒跚,事情真的会变慢,那将会发生什么。 同样,如果程序运行足够长的时间可以更好地收集垃圾,否则,运行的新代码可能会变慢,并且如果对它进行基准测试,则可能会显示错误的结果。
现在,让我们看看其他内容。 你们都知道计算机有内存。 当程序运行时,它需要记住事情并消耗一些内存,有时当可用内存变少时,Ruby 解释器将清理内存。 这称为垃圾收集 &lt;sup class="footnote"&gt;[ [62](#_footnotedef_62 "View footnote.") ]&lt;/sup&gt; 。 就像你的城市或市政当局收集垃圾一样,城市运行正常。 现在想想,如果不收集垃圾,而你遇到的垃圾会流到街道上,整个城市步履蹒跚,事情真的会变慢,那将会发生什么。 同样,如果程序运行足够长的时间可以更好地收集垃圾,否则,运行的新代码可能会变慢,并且如果对它进行基准测试,则可能会显示错误的结果。
现在,在文本编辑器中键入以下程序并运行它。
......@@ -152,7 +152,7 @@ Rehearsal --------------------------------------
<< 0.010000 0.000000 0.010000 ( 0.015668)
```
如果看到此代码产生的第一个基准测试
如果看到此代码产生的第一个基准测试
```rb
puts "Testing without cleaning up"
......@@ -214,4 +214,4 @@ Rehearsal --------------------------------------
----------------------------- total: 0.720000sec
```
如果您可以比较不带 GC 的`100_000.times { a &lt;&lt; "." }`的输出和带 GC 的`100_000.times { a &lt;&lt; "." }`的输出,分别为 0.16 秒和 0.02 秒。 现在,我想您会意识到垃圾收集的需要,无论是在城市中还是在编程中。
\ No newline at end of file
如果你可以比较不带 GC 的`100_000.times { a &lt;&lt; "." }`的输出和带 GC 的`100_000.times { a &lt;&lt; "." }`的输出,分别为 0.16 秒和 0.02 秒。 现在,我想你会意识到垃圾收集的需要,无论是在城市中还是在编程中。
\ No newline at end of file
## 27.测试驱动开发
假设您在马戏团中,一个漂亮的女孩正在空中飞人表演,她错过了抓地力并摔倒了,您希望那里有一个安全网来捉住她吗? 您必须疯了才能拒绝。 以类似的方式,可以说您正在开发软件,犯了一个错误,使用该软件的人会付出很多代价,拥有制衡能力不是一件好事,这样即使在错误发生之前就可以知道该错误。 软件已发货?
假设你在马戏团中,一个漂亮的女孩正在空中飞人表演,她错过了抓地力并摔倒了,你希望那里有一个安全网来捉住她吗? 你必须疯了才能拒绝。 以类似的方式,可以说你正在开发软件,犯了一个错误,使用该软件的人会付出很多代价,拥有制衡能力不是一件好事,这样即使在错误发生之前就可以知道该错误。 软件已发货?
欢迎来到测试驱动开发。 在这种方法中,我们首先编写测试,然后编写足够的代码来满足测试。 通过遵循这种方法,我能够以最大的信心进行编码,并且能够知道存在安全网以防万一我做错了事,从而能够更改代码并使之更好(也称为重构)。
让我们想象一个场景。 的任务是编写聊天机器人程序,其初始要求如图所示
让我们想象一个场景。 的任务是编写聊天机器人程序,其初始要求如图所示
* 必须有一个聊天机器人
* 一个人必须能够设定年龄和名字
* 它的问候语必须是:“您好,我叫&lt;,名字叫&gt;,我的年龄是&lt;,年龄&gt;,很高兴认识您!”
* 它的问候语必须是:“你好,我叫&lt;,名字叫&gt;,我的年龄是&lt;,年龄&gt;,很高兴认识你!”
通常,要求不会像上面显示的那样精确,但是作为一名程序员,应该可以考虑一下。 现在,我们开始编写测试文件,而不是编写代码来解决任务,将其命名为 test_chat_bot.rb 并将需求放入其中,如下所示:
......@@ -96,7 +96,7 @@ end
end
```
如果您想知道这些内容,让我来解释一下`assert_kind_of`。 这些称为断言。 您可以在此处查看哪些断言 [http://ruby-doc.org/stdlib-2.0.0/libdoc/minitest/rdoc/MiniTest/Assertions.html#method-i-assert_respond_to](http://ruby-doc.org/stdlib-2.0.0/libdoc/minitest/rdoc/MiniTest/Assertions.html#method-i-assert_respond_to)
如果你想知道这些内容,让我来解释一下`assert_kind_of`。 这些称为断言。 你可以在此处查看哪些断言 [http://ruby-doc.org/stdlib-2.0.0/libdoc/minitest/rdoc/MiniTest/Assertions.html#method-i-assert_respond_to](http://ruby-doc.org/stdlib-2.0.0/libdoc/minitest/rdoc/MiniTest/Assertions.html#method-i-assert_respond_to)
断言是用于验证天气是否发生某些预期事件的函数,如果发生,则表示测试已通过,否则测试已失败。
......@@ -167,7 +167,7 @@ Finished in 0.000720s, 1388.5244 runs/s, 1388.5244 assertions/s.
1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
```
我们做了什么? 我们有一个需求,我们编写了涵盖该需求的测试,我们运行了测试,但失败了,通过了,我们编写了足以使它通过的代码。 现在想象一个场景,您正在一个有 10 个开发人员的项目中,其中一个偶然地犯了一个错误,该错误将重命名此`ChatBot`类,并且您的测试将抓住它。 简而言之,如果您编写了足够的测试,则可以提早发现错误。 它不能保证没有错误的代码,但是会使错误弹出更加困难。 这些测试还将使您有信心重构代码。 假设您进行了更改,则不必担心您的更改可能会造成严重破坏,只需运行测试一次,您将获得有关失败和通过的报告。
我们做了什么? 我们有一个需求,我们编写了涵盖该需求的测试,我们运行了测试,但失败了,通过了,我们编写了足以使它通过的代码。 现在想象一个场景,你正在一个有 10 个开发人员的项目中,其中一个偶然地犯了一个错误,该错误将重命名此`ChatBot`类,并且你的测试将抓住它。 简而言之,如果你编写了足够的测试,则可以提早发现错误。 它不能保证没有错误的代码,但是会使错误弹出更加困难。 这些测试还将使你有信心重构代码。 假设你进行了更改,则不必担心你的更改可能会造成严重破坏,只需运行测试一次,你将获得有关失败和通过的报告。
让我们编写另一个测试,一个应该能够给聊天机器人一个`age`。 因此,让我们编写一个测试,在其中可以设置它的年龄并重新读取它。 查看下面的函数`test_one_must_be_able_to_set_its_age`中的代码
......@@ -218,7 +218,7 @@ NoMethodError: undefined method `age=' for #<ChatBot:0x0000558b89da5380>
2 runs, 1 assertions, 0 failures, 1 errors, 0 skips
```
如果看到上面的测试结果,则说明没有方法错误,并说明缺少函数`age=`,因此请对其进行修复。
如果看到上面的测试结果,则说明没有方法错误,并说明缺少函数`age=`,因此请对其进行修复。
```rb
# chat_bot.rb
......@@ -287,7 +287,7 @@ class TestChatBot < Minitest::Test
end
```
现在我们运行它,如所见,它自然会失败,如下所示
现在我们运行它,如所见,它自然会失败,如下所示
```rb
$ ruby test_chat_bot.rb
......@@ -344,4 +344,4 @@ Finished in 0.001149s, 3480.2007 runs/s, 3480.2007 assertions/s.
与现在使用的软件相比,当软件开始时,它很小,计算机功率很低,并且只能用于非常艰巨的任务,所以人们对单个人或紧密联系的小组可以维护的小程序感到满意。 但是,随着计算机变得越来越强大,计算机变得越来越复杂,项目变得越来越庞大,代码的结构成为一个重要的问题。 那就是设计模式揭晓的时候。
阅读本书的大多数人可能是 Ruby 初学者或中级,但是您可能需要从事实际项目。 即使您为个人项目选择了 Ruby,也更好地组织代码,因此对设计模式的需求变得至关重要。
\ No newline at end of file
阅读本书的大多数人可能是 Ruby 初学者或中级,但是你可能需要从事实际项目。 即使你为个人项目选择了 Ruby,也更好地组织代码,因此对设计模式的需求变得至关重要。
\ No newline at end of file
## 28.观察者模式
面向对象编程是根据现实世界建模的。 这里,对象需要彼此通信,其他对象需要在一个对象状态改变时做出反应。 假设遇到一种情况,即对象的状态更改需要传播到 n 个其他对象,这些其他对象称为观察者。 当事情发生变化时,如何编写整洁的代码来通知观察者? 欢迎使用观察者模式。
面向对象编程是根据现实世界建模的。 这里,对象需要彼此通信,其他对象需要在一个对象状态改变时做出反应。 假设遇到一种情况,即对象的状态更改需要传播到 n 个其他对象,这些其他对象称为观察者。 当事情发生变化时,如何编写整洁的代码来通知观察者? 欢迎使用观察者模式。
看一下 [rator.rb](code/design_patterns/observer.rb) ,代码清单如下所示
......@@ -89,7 +89,7 @@ vel.observers << Person.new("Swami")
因此,从上面的代码中我们知道,有一个名叫 Vel 的人被 Murugan 和 Swami 观察到。 想象一下一个社交网络,Vel 之后是 Murugan 和 Swami。 因此,我们在`Person`中有一个称为`observers`的属性,它不过是一个可以容纳尽可能多观察者的数组。
如果查看 [Observer.rb](code/design_patterns/observer.rb) ,会注意到它已在以下几行中完成
如果查看 [Observer.rb](code/design_patterns/observer.rb) ,会注意到它已在以下几行中完成
```rb
class Person
......@@ -117,7 +117,7 @@ Vel: Hello All! - notified to Murugan
Vel: Hello All! - notified to Swami
```
因此,可以看到观察者已收到有关 Vel 的新状态的通知。 如何完成的? 如果查看 [viewer.rb](code/design_patterns/observer.rb) ,则在方法`set_status`中我们将调用方法`notify_observers`,在其中发生了魔术。
因此,可以看到观察者已收到有关 Vel 的新状态的通知。 如何完成的? 如果查看 [viewer.rb](code/design_patterns/observer.rb) ,则在方法`set_status`中我们将调用方法`notify_observers`,在其中发生了魔术。
看看`notify_observers`方法
......@@ -158,4 +158,4 @@ end
这就是观察者模式的工作方式。 我们有存储观察者的方法,有一个通知观察者的方法,当需要进行通知时会调用该方法,最后我们有一个方法是观察者来接收更改的对象。 观察者可以对更改后的对象执行其希望的操作。
| | 实际上,当您使用 Ruby 时,观察者模式会直接放入其标准库中。 看看这个 https://ruby-doc.org/stdlib-2.7.0/libdoc/observer/rdoc/Observable.html |
\ No newline at end of file
| | 实际上,当你使用 Ruby 时,观察者模式会直接放入其标准库中。 看看这个 https://ruby-doc.org/stdlib-2.7.0/libdoc/observer/rdoc/Observable.html |
\ No newline at end of file
......@@ -167,7 +167,7 @@ PlainText.new(
).print
```
因此,如果看到的话,模板模式定义了基本模板或结构,从而为想要扩展它的类带来了清晰度和结构。 这也可以减少在派生类中需要完成的编码。
因此,如果看到的话,模板模式定义了基本模板或结构,从而为想要扩展它的类带来了清晰度和结构。 这也可以减少在派生类中需要完成的编码。
### 29.1。 行使
......
## 30.工厂模式
想象一下一家餐馆,它实际上是一家食品工厂。 如果您需要 dosa &lt;sup class="footnote"&gt;[ [64](#_footnotedef_64 "View footnote.") ]&lt;/sup&gt; ,请问服务员,如果您需要 idiyappam &lt;sup class="footnote"&gt;[ [65](#_footnotedef_65 "View footnote.") ]&lt;/sup&gt; ,请问服务员 它。 本质上,饭店或食品工厂创建了一个称为服务员的通用界面,供您订购任何东西。 您只问他,他就送了,您不必关心 dosa 的制作方式或 idiyappam 的制作方式。
想象一下一家餐馆,它实际上是一家食品工厂。 如果你需要 dosa &lt;sup class="footnote"&gt;[ [64](#_footnotedef_64 "View footnote.") ]&lt;/sup&gt; ,请问服务员,如果你需要 idiyappam &lt;sup class="footnote"&gt;[ [65](#_footnotedef_65 "View footnote.") ]&lt;/sup&gt; ,请问服务员 它。 本质上,饭店或食品工厂创建了一个称为服务员的通用界面,供你订购任何东西。 你只问他,他就送了,你不必关心 dosa 的制作方式或 idiyappam 的制作方式。
在编程中,您可以做同样的事情,您可以实现一个工厂类,该类隐藏了制造对象的困难,并为您提供了一个通用的接口来制造对象。 看下面的代码 [factory.rb](code/design_patterns/factory.rb) 。 输入并运行它。
在编程中,你可以做同样的事情,你可以实现一个工厂类,该类隐藏了制造对象的困难,并为你提供了一个通用的接口来制造对象。 看下面的代码 [factory.rb](code/design_patterns/factory.rb) 。 输入并运行它。
```rb
```
......@@ -99,4 +99,4 @@ end
### 30.1。 行使
想象一下,您正在编写用于游戏的软件,并且需要创建敌对对象,例如坦克,直升机,导弹发射器,步兵等。 编写一个工厂模式,当您调用`Enemy.random`时会返回一个随机的敌人对象。
\ No newline at end of file
想象一下,你正在编写用于游戏的软件,并且需要创建敌对对象,例如坦克,直升机,导弹发射器,步兵等。 编写一个工厂模式,当你调用`Enemy.random`时会返回一个随机的敌人对象。
\ No newline at end of file
## 33.单例模式
想象一下,如果您在一个房子里开派对,并且预计要有 20 位客人,那么每位客人都必须进入您的房间,因此每位客人都需要一扇门,因此您开始砸墙并开始为 20 扇门腾出空间。 听起来不疯狂吗? 您不认为只有一扇门可以达到这个目的吗?
想象一下,如果你在一个房子里开派对,并且预计要有 20 位客人,那么每位客人都必须进入你的房间,因此每位客人都需要一扇门,因此你开始砸墙并开始为 20 扇门腾出空间。 听起来不疯狂吗? 你不认为只有一扇门可以达到这个目的吗?
假设您想在 Ruby 程序中访问数据库。 您可以编写一个类来连接它并返​​回结果。 假设您的程序正在与数据库同时建立 10 个连接,那么您认为复制数据库用户名,密码和查询程序的逻辑在您计算机 RAM 的 10 个位置中存在吗? 还是您认为将它放在一个地方并可以被所有人使用是有效的?
假设你想在 Ruby 程序中访问数据库。 你可以编写一个类来连接它并返​​回结果。 假设你的程序正在与数据库同时建立 10 个连接,那么你认为复制数据库用户名,密码和查询程序的逻辑在你计算机 RAM 的 10 个位置中存在吗? 还是你认为将它放在一个地方并可以被所有人使用是有效的?
欢迎使用 Singleton 模式,无论如何,即使创建了 100 万次,Singleton 对象也可以将其存储在计算机 RAM 中的一个位置,从而节省了计算机空间。
......
......@@ -166,9 +166,9 @@ class BoiledEggs < Node
end
```
`BoiledEggs`继承了一个名为`Node`的类,该类有助于构建树结构。 稍后再讨论`Node`类。 现在让我们专注于复合模式。 如在`initialize`方法中所见,在该类中`BoiledEggs`被划分为许多类,即`BuyEggs`至`ServeEggs`,并且它们被作为子节点添加到`BoiledEggs`中。
`BoiledEggs`继承了一个名为`Node`的类,该类有助于构建树结构。 稍后再讨论`Node`类。 现在让我们专注于复合模式。 如在`initialize`方法中所见,在该类中`BoiledEggs`被划分为许多类,即`BuyEggs`至`ServeEggs`,并且它们被作为子节点添加到`BoiledEggs`中。
如果可以看到类`BuyEggs`如下所示:
如果可以看到类`BuyEggs`如下所示:
```rb
class BuyEggs < Node
......@@ -216,7 +216,7 @@ end
因此,复合模式可以用于存在复杂对象的地方,可以将其功能分解为较小的对象,可以以非常相似的方式处理这些较小的对象,并将这些较小的对象放置在树状结构中。
谈论树结构,我们建立了一个名为`Node`的类,可以在文件 [node.rb](code/design_patterns/node.rb) 中找到该类。 可以在下面看到它。
谈论树结构,我们建立了一个名为`Node`的类,可以在文件 [node.rb](code/design_patterns/node.rb) 中找到该类。 可以在下面看到它。
```rb
```
......@@ -267,7 +267,7 @@ end
|
```
它具有一个称为`add_child`的功能,通过它我们可以添加子元素。 可以使用`parent`功能获取节点的父节点。 要查看此节点类的工作方式,请看下面的代码 [Composite.rb](code/design_patterns/composite.rb) :
它具有一个称为`add_child`的功能,通过它我们可以添加子元素。 可以使用`parent`功能获取节点的父节点。 要查看此节点类的工作方式,请看下面的代码 [Composite.rb](code/design_patterns/composite.rb) :
```rb
```
......
## 35.建造者模式
假设正在为网站提供高度定制化功能的计算机制造商编写一款软件。 一台计算机可以有很多零件,它们可以变化,因此有很多组合。 因此,我们不是将所有这些代码放在一个单一的大型计算机类中,而是创建了一个名为 builder 的类,在这种情况下,我们创建了一个名为`ComputerBuilder`的类,该类承担创建定制计算机的任务,并可能简化创建或创建过程。 构建过程也是如此。
假设正在为网站提供高度定制化功能的计算机制造商编写一款软件。 一台计算机可以有很多零件,它们可以变化,因此有很多组合。 因此,我们不是将所有这些代码放在一个单一的大型计算机类中,而是创建了一个名为 builder 的类,在这种情况下,我们创建了一个名为`ComputerBuilder`的类,该类承担创建定制计算机的任务,并可能简化创建或创建过程。 构建过程也是如此。
假设我们需要不同类型的 CPU 来构建计算机,为此,我们编写了三种类型的 CPU 类,如下所示 [cpus.rb](code/design_patterns/builder/cpus.rb)
......@@ -39,7 +39,7 @@ end
|
```
计算机可能需要驱动器,我们也为此编写了一个类,如果看到下面的代码 [drive.rb](code/design_patterns/builder/drive.rb) ,则为该驱动器提供了一个类以及一个可用于自定义的初始化程序 在一定程度上。
计算机可能需要驱动器,我们也为此编写了一个类,如果看到下面的代码 [drive.rb](code/design_patterns/builder/drive.rb) ,则为该驱动器提供了一个类以及一个可用于自定义的初始化程序 在一定程度上。
```rb
```
......@@ -249,9 +249,9 @@ end
|
```
在上面的程序中,第 4 行中确实有`initialize`方法,但是如果您查看第 44 行,则在方法`computer`中将返回`Computer`实例。 如果您看到的是同一功能,那么如果没有足够的内存,或者如果计算机中添加了太多磁盘,则我们有代码引发异常。 因此,这是构建器模式的另一个优点,在该模型中,如果不满足特定条件,就可以防止构建复杂的对象。
在上面的程序中,第 4 行中确实有`initialize`方法,但是如果你查看第 44 行,则在方法`computer`中将返回`Computer`实例。 如果你看到的是同一功能,那么如果没有足够的内存,或者如果计算机中添加了太多磁盘,则我们有代码引发异常。 因此,这是构建器模式的另一个优点,在该模型中,如果不满足特定条件,就可以防止构建复杂的对象。
在构建器中,具有`display`,`memory_size`之类的方法,以及名为`turbo`的函数来设置显示,内存和 CPU 类型的参数。 我们还具有`add_cd`,`add_dvd`和`add_hard_disk`之类的功能,可将这些内容添加到我们正在构建的计算机中。
在构建器中,具有`display`,`memory_size`之类的方法,以及名为`turbo`的函数来设置显示,内存和 CPU 类型的参数。 我们还具有`add_cd`,`add_dvd`和`add_hard_disk`之类的功能,可将这些内容添加到我们正在构建的计算机中。
现在让我们看一下将所有内容组合在一起的程序。 看看下面的程序 [main.rb](code/design_patterns/builder/main.rb) ,键入或复制并执行它。
......@@ -414,7 +414,7 @@ computers = []
computers.each { |computer| puts computer }
```
| | 假设正在编写游戏,并且需要创建 10 个对象,这种模式将非常方便。 |
| | 假设正在编写游戏,并且需要创建 10 个对象,这种模式将非常方便。 |
现在,让我们测试如果内存不足则将引发异常的代码。 看下面的代码
......@@ -460,7 +460,7 @@ Too many drives.
### 35.1。 行使
您现在了解了构建器模式。 如果您想进一步探索,请看下面的代码
你现在了解了构建器模式。 如果你想进一步探索,请看下面的代码
```rb
# use magic method to rapidly build a computer
......
## 36.策略模式
无论您是否意识到自己是一名出色的战略家。 早上醒来时,您会去喝咖啡,如果没有咖啡粉,您可能会喝杯茶或热巧克力或牛奶。 您开车去上班或上学,如果某条路受阻,则采取另一种方式。 在工作中,您需要考虑向老板呈现的方式,是否使老板心情愉快的方式,以便您可以谈论事实或掩盖事实。 策略无处不在,您只是没有注意到它。 您每次都会根据环境 &lt;sup class="footnote"&gt;[ [68](#_footnotedef_68 "View footnote.") ]&lt;/sup&gt; 不断采用新策略。
无论你是否意识到自己是一名出色的战略家。 早上醒来时,你会去喝咖啡,如果没有咖啡粉,你可能会喝杯茶或热巧克力或牛奶。 你开车去上班或上学,如果某条路受阻,则采取另一种方式。 在工作中,你需要考虑向老板呈现的方式,是否使老板心情愉快的方式,以便你可以谈论事实或掩盖事实。 策略无处不在,你只是没有注意到它。 你每次都会根据环境 &lt;sup class="footnote"&gt;[ [68](#_footnotedef_68 "View footnote.") ]&lt;/sup&gt; 不断采用新策略。
在计算世界中,如果我们能够根据传递的标志/参数告诉一段代码动态运行不同的算法,则这种编码称为策略模式。 让我们看下面的示例 [strategy_pattern.rb](code/design_patterns/strategy_pattern.rb)
......@@ -166,7 +166,7 @@ def self.generate(data, formatter)
end
```
在这里,我们将`formatter`作为第二个参数,即本例中的`NewsFormatter::HTML`,并将其传递给`data`作为参数,从而对其调用`format`方法。 因此,程序控制转到第 12 行,该行位于模块`NewsFormatter`内,并进入类`HTML`中的方法`self.format`中,可以在此处看到代码段
在这里,我们将`formatter`作为第二个参数,即本例中的`NewsFormatter::HTML`,并将其传递给`data`作为参数,从而对其调用`format`方法。 因此,程序控制转到第 12 行,该行位于模块`NewsFormatter`内,并进入类`HTML`中的方法`self.format`中,可以在此处看到代码段
```rb
module NewsFormatter
......@@ -201,7 +201,7 @@ module NewsFormatter
end
```
那就是调用了模块`NewsFormatter`中类`Text`中的函数`self.format`,该函数会产生纯文本输出,如项目符号,因此将看到以下输出:
那就是调用了模块`NewsFormatter`中类`Text`中的函数`self.format`,该函数会产生纯文本输出,如项目符号,因此将看到以下输出:
```rb
* You are reading I Love Ruby.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册