Ruby快速入门(30分钟)

在本教程中,将探讨使用Ruby开始编程所需的基本语法,以及如何在30分钟内快速入门学习并使用Ruby编程语言。

注:如果您还尚未安装Ruby开发环境,请访问环境设置页面并按照说明安装: http://www.yiibai.com/ruby/ruby-installation.html

Ruby 历史

Ruby被许多人认为是一种“新”编程语言,但实际上是由一个叫作Matz的开发人员于1994年发布的。 Matz自我描述是一个“语言极客”,也是Perl大粉丝。 他对Ruby的想法是创建一种像Perl这样灵活而强大的语言,但在其语法上更具表现力 - 甚至可以具有类似于英语那样的可读性。

Ruby在日本迅速成长,直到2000年,真的没有关于除了日本语言以外的任何文档。所以如果想要学习Ruby,那得必须先学习日语。 敏捷编程的先驱Dave Thomas被Ruby迷住,并决定创建Ruby的其它语言文档。

自Ruby有了英文开始,Ruby就开始在英语世界中增长,尽管缓慢。 系统管理员变得流行,编写维护和“粘贴”脚本 - 类似Perl的用法。从2000年到2005年美国的Ruby社区已达数百个。

在2004-2005年,一家名为37Signals的芝加哥公司聘请了一名年轻的开发人员来构建一个Web应用程序。 公司给了他几乎完全的执行自由; 他们只关心客户端的设计和功能。 当时主要的Web技术是Perl CGI,PHP,Java的JSP和Microsoft的ASP。 但是他们都是有点痛苦,但DHH的大卫(DHH)选择了自己的方向。他在Ruby中写了这个应用程序。 他依靠核心库和少数库的帮助下,同时自己创建了整个堆栈(或多或少)。37Signals在Web应用程序使用Ruby来编写,这个项目今天被称为Basecamp

当建立了Basecamp,DHH就会从中提取出Web框架。 这是一个非常不同的方法,从Java/Sun.NET/Microsoft,Web框架都是从高处往下传播。 相反,Rails从现实世界中抽出来。 它侧重于常规配置,使常见问题更容易解决。

这种方法是一个很大的打击,Rails自从以来一直推动了Ruby/Rails社区的发展。 现在,在亚马逊上有数十本书,全球近一百个会议,有成千上万的人是Ruby/Rails开发人员。

如果你想学习Rails,需要先学习Ruby! 现在就开始咯 .....

1. Ruby解释器

Ruby是一种“解释”的编程语言,它不能直接在处理器上运行,它的代码必须馈送到称为“虚拟机”或虚拟机的中间件。 虚拟机的一方面是Ruby代码,另一方面则是操作系统和处理器。 这种方法的好处是您可以编写一次Ruby代码,就可以在许多不同的操作系统和硬件平台上执行了。

Ruby程序无法运行自己的程序,它需要加载虚拟机。 使用VM执行Ruby的方式有两种:通过IRB和命令行。

从命令行运行Ruby代码

这是编写Ruby代码的耐用方法,因为要将指令保存到文件中。 该文件可以备份,传输,添加到源代码管理等。

一个Ruby代码文件示例

这里创建一个名称为:first-ruby.rb的文件,如下所示:

#!/usr/bin/ruby   
# filename : first-ruby.rb

class Sample
  def hello
    puts "Hello, World!"
  end
end

s = Sample.new
s.hello

那么可以这样运行程序:

当您运行ruby first-ruby.rb时,实际上正在加载ruby虚拟机,然后再加载first-ruby.rb文件中的代码。

从IRB运行Ruby代码

Ruby是第一批语言推广所谓“REPL”:阅读,评估,打印,循环的编程语言。想像它就像一个计算器 - 就像在每个完整的指令中,IRB执行这些指令并显示结果。

IRB最好用作实验的便笺簿。 许多开发人员在编写他们的“真实”程序时,一般都保持IRB窗口打开,使用它来记住某个方法如何工作或用于调试某个代码块。

要打开IRB进行实验,可通过打开终端(Mac)或命令提示符(Win)并打开或输入irb来启动IRB。以Windows系统为例,如下所示 -

注: 按 Ctrl + D 可退出 irb 模式。

2. Ruby变量

编程都是要创建抽象的代码来描述和处理数据,要创建抽象,必须要为在代码中分配名称来表示事物。 变量只不过是为数据创建一个名称的一种方式。

创建和分配变量

在某些语言中,需要在为一个变量分配值之前声明这个变量。 当为变量分配值时,会自动创建Ruby变量。下面来试试一个例子:

a = 250表示创建一个名称为a的变量,并将值250存储到其中。

右边优先

在英文表达式中,是从左到右阅读,所以从左到右读取代码是很自然的。 但是当使用单个等于号(=)评估求值一个赋值时,Ruby实际上首先评估求值右侧。 举个例子:

irb(main):010:0> b = 10 + 20
=> 30
irb(main):011:0> b
=> 30
irb(main):012:0>

上面示例中,首先对10 + 20进行评估求值,再将求值结果存储到b变量中。

灵活输入

Ruby的变量可以容纳任何类型的数据,甚至可以更改其持有的数据类型。 例如:

irb(main):012:0> c = 200
=> 200
irb(main):013:0> c = "Flexible Typing"
=> "Flexible Typing"
irb(main):014:0> c
=> "Flexible Typing"
irb(main):015:0> c = 0.0001
=> 0.0001
irb(main):016:0> c
=> 0.0001
irb(main):017:0>

第一次赋予c变量为一个200的整数值。第二次赋值是将c变量的值更改其为“Flexible Typing”。

命名变量

大多数Ruby变量(局部变量)的命名都有一些由VM强制的要求。这些要求约定如下 -

  • 始终以小写字母开头(允许下划线,虽然不常见)
  • 不能使用空格
  • 不要包含特殊字符,如$@

除了那些虚拟机的要求,Ruby开发者对变量名称有几个常见风格偏好:

  • 使用蛇形大小写,即:名称中的每个字都是小写字母,并用下划线(_)连接
  • 以其内容的含义命名,而不是其内容的类型
  • 不使用缩写

好的变量名的示例如下:counttotal_productsstudents_in_classfirst_lesson

一些不好的Ruby变量名称的几个例子,如下所示:

  • studentsInClass – 使用骆驼案而不是蛇形大小写,应该命名为:students_in_class
  • 1st_lesson – 变量不能以数字开头,应该命名为:first_lesson
  • students_array – 包括名称的数据类型,应该命名为:students
  • sts – 不使用缩写,应该命名为:students

练习

使用IRB存储每个以下变量名称的值。 哪些名字是好的,哪些是是无效的Ruby变量名称,哪些是有效的,哪些是Ruby不建议使用的风格?

  • time_machine
  • student_count_integer
  • homeworkAssignment
  • 3_sections
  • top_ppl

3. 字符串

在现实世界中,字符串是将一个个字符串联起来的。 编程中的字符串与真实字符串无关。

编程中的字符串用于存储字母和数字的集合。它可以是一个单一的字母,如“a”,或者像“hi”这样一个单词,或者“Hello my friends.”这样的一段话。

编写一个字符串

Ruby字符串被定义为一个引号("),后跟零个或多个字母,数字或符号,后跟一个闭包引号(")。 最短的字符串称为空字符串:""。 单个字符串包含文本的段落甚至页面也很常见。

子字符串

通常使用字符串,可从整个长字符串提取出来的一部分 - 这提取出来的部分称为子字符串。在 irb 尝试这些例子:

irb(main):017:0> string = "Ruby in 30 Minutes at yiibai.com"
=> "Ruby in 30 Minutes at yiibai.com"
irb(main):018:0> string[0..8]
=> "Ruby in 3"
irb(main):019:0> string[8..16]
=> "30 Minute"
irb(main):020:0> string[8..-1]
=> "30 Minutes at yiibai.com"
irb(main):021:0> string[8..-2]
=> "30 Minutes at yiibai.co"
irb(main):022:0>

正号和负号的位置

字符串中的字符每个都有一个位置编号,它们从零开始。 所以对于字符串中的开头“Ru”,“R”位置编号为0,“u”所在的位置编号为1

要在主字符串中提取出一个子串,可指定提取的起始位置和结束位置。 因此,上面的string[0..8]提取出位置从08的字母,也就是:“Ruby in 3”。

Ruby解释负的位置从字符串的末尾返回。所以在上面示例中,结尾的字符串“com”的字母分别对应为“m”位于-1,“o”位于-2 和 “c”位于-3

所以如果一个字母同时有正数和负数的位置,那么应该使用哪个? 建议使用正数,因为这样它们更容易理解。 但是,如果要基于字符串末尾查找东西(例如“该字符串的最后一个字符是什么?”),则使用负数指定位置。

常用的字符串方法

在IRB中使用字符串(对象)中一些常用的方法。

.length

length方法用于求出字符串中有多少个字符(包括空格):

irb(main):022:0> string = "0123456789"
=> "0123456789"
irb(main):023:0> string.length
=> 10
irb(main):024:0> string = "maxsu"
=> "maxsu"
irb(main):025:0> string.length
=> 5
irb(main):026:0>

尝试:计算你的名字的总长度

.split

有时想要将一个字符串分成几部分。 例如,假设有一个存储为字符串的句子,并将其分解成单词:

C:\Users\Administrator>irb
irb(main):001:0> string = "This is my sample sentence."
=> "This is my sample sentence."
irb(main):002:0> string.split
=> ["This", "is", "my", "sample", "sentence."]
irb(main):003:0>

.split方法返回一个数组,这将在后面的部分讲解中了解到。 它默认使用空格(“”)字符将字符串分割成多个部分。

.split使用参数

但有时要分割的不是一个带有空格的字符。 .split方法接受一个参数来指定分隔符,看看下面示例就明白了。

irb(main):003:0> numbers = "1,2,3,4,5,6,7,8"
=> "1,2,3,4,5,6,7,8"
irb(main):004:0> numbers.split
=> ["1,2,3,4,5,6,7,8"]
irb(main):005:0> numbers.split(",")
=> ["1", "2", "3", "4", "5", "6", "7", "8"]
irb(main):006:0>

在第一次分割的调用中,它尝试使用空格作为分隔符,但字符串中没有分隔符,所以得到一个整个字符串的数组。 在第二次尝试中,指定使用逗号(",")作为分隔符,所以得到一个8个数字值的数组。

.sub 和 .gsub

这两种方法可以用来替换字符串的部分。它们就像在文字处理器中使用“查找和替换”。 .sub替换只发生一次。 而.gsub全局替换的缩写,替换所有的发生(如“全部替换”)。

对于.sub.gsub,需要指定两个参数:首先是要替换的子字符串,然后再替换要替换的字符串。

irb(main):013:0> greeting = "Hello, Hello Everyone!"
=> "Hello, Hello Everyone!"
irb(main):014:0> greeting.sub("Hello","Hi")
=> "Hi, Hello Everyone!"
irb(main):015:0> greeting.gsub("Hello","Hi")
=> "Hi, Hi Everyone!"
irb(main):016:0>

组合字符串和变量

将变量的值与字符串相结合这是在开发应用程序中最经常使用的。 例如,现在从下面这个例子开始:

"Good morning, ?? !"

当把上面语句放入IRB时,它只是打印输出同一个字符串。 如果编写一个应用程序,希望它以用户名而不是“??”来跟用户打招呼,那么需要怎么做?

需要做的就是将变量与字符串组合。有两种方法可以做到这一点。

方法-1. 字符串连接

第一种方法,可使用字符串连接,它将字符串与加号连接:

irb(main):021:0> name = "Maxsu"
=> "Maxsu"
irb(main):022:0> puts "Good morning, " + name + " ! "
Good morning, Maxsu !
=> nil
irb(main):023:0>

在第一行中,设置了一个name变量来保存名称。 在第二行,打印字符串“Good morning" 并结合"name"变量和字符串"!"的值。

方法-2. 字符串插值

第二种方法是使用字符串插值,将数据粘贴到字符串的中间。

字符串插值仅适用于双引号字符串。在字符串内使用插值标记#{}。 在这些括号中可以把任何变量或Ruby代码放入其中,这些变量或Ruby代码将被评估求值,其结果转换为一个字符串,并输出到外部字符串的那个位置。 上面的例子可以这样重写:

irb(main):023:0> name = "Maxsu"
=> "Maxsu"
irb(main):024:0> puts "Good morning, #{name}!"
Good morning, Maxsu!
=> nil
irb(main):025:0>

如果比较输出结果,就会看到它们输出的是完全相同的结果。 内插样式往往是输入较少的字符类型,较少的双引号打开/关闭,所以可避免加双引号时忘记书写对称(往往有输入多一个,少一个的问题)。

内插插入代码

还可以将任何Ruby代码或计算表达式内置在括号内,如下所示:

irb(main):025:0> modifier = "very "
=> "very "
irb(main):026:0> mood = "excited"
=> "excited"
irb(main):028:0> puts "I am #{modifier * 3 + mood} for today's play!"
I am very very very excited for today's play!
=> nil
irb(main):029:0>

首先对#{modifier * 3 + mood}代码块进行评估求值,然后将结果注入外部字符串中。

4. 符号

符号有点难以解释,它们是字符串和数字的一半。但是可以很容易识别一个符号,因为它是以冒号开始一个或多个字母,如:flag:best_friend

新程序员的符号

如果你是编程的新手,可将一个符号看作是一个几乎没有任何方法和没有字符串插值的被剥离下来的字符串。 将正确的字符串与类似符号的方法列表进行比较,如下所示:

2.1.1 :001> "hello".methods
2.1.1 :002> "hello".methods.count
2.1.1 :003> :hello.methods
2.1.1 :004> :hello.methods.count

有经验的程序员的符号

如果你是一个有经验的程序员,想象一个符号是一个“命名整数”。 符号引用的实际值无关紧要。 我们所关心的是,虚拟机内对该值的任何引用将返回相同的值。 因此,符号在全局符号表中定义,它们的值不能改变。

5. 数字值

数字有两种基本类型:整数(整数)和浮点数(有小数点)。
整数对于您和计算机来说都要容易一些。 您可以使用包括+-/*在内的整数的正常数学运算。 整数有一些方法可以用来做数学相关的事情,过调用5.methods方法就可看到一些常用的方法。

重复指令

重复执行指令在其他语言中的常见模式是for循环,用于重复执行某些指令一定次数。 例如,在JavaScript中可以写:

for(var i = 0; i < 5; i++){
  console.log("Hello, World");
}

对于循环是很常见的,但它们的代码不是很容易阅读。 因为Ruby的整数是它们拥有方法的对象。 其中的一个方法:times是重复执行指令的方法。

以Ruby样式重写上述循环:

5.times do
  puts "Hello, World!"
end

在这个例子中,使用times方法和具体的执行代码块。 在下一节中将讨论块。 但是请先在IRB中运行这个例子,看看结果会是什么。

6. 块

块是Ruby中经常使用的强大概念。 可将块视为一组捆绑在其他地方使用的指令的方式。

块的开始和结束

在上一节中有一个使用.times方法的块用整数表示:

5.times do
  puts "Hello, World!"
end

该块以关键字do开始,以关键字end结束。 do/end风格总是可以被Ruby解释器所接受的。

支架块

当块仅包含单个指令时,经常使用备用标记{}来标识块的开始和结束:

5.times{ puts "Hello, World!" }

块被传递给方法

那么使用块来做什么? 块可以用来作为传递给方法调用的参数。

例如,如果调用了5.times,Ruby就不会知道要执行五次了。当通过块时,就会说“这里是希望每次运行的说明”。

块中有很多的方法。 就像前面看到的.gsub方法一样,字符串早就为每个匹配运行一个块:

irb(main):038:0> "this is a sentence".gsub("e"){ puts "Found an E!"}
Found an E!
Found an E!
Found an E!
=> "this is a sntnc"
irb(main):039:0>

请注意,"Found an E!"显示了三次,因为字符串中有三个E字母。

块参数

通常,在块内指示需要引用正在使用的值。 当在编写块代码时,可以在管道字符中指定一个块参数:

5.times do |i|
  puts "Hello, World! "
end

什么值应该放入该块参数,这取决于要调用的方法。 在本示例中,times方法放入当前运行的数值。尝试上面的块,观察输出,然后尝试这样修改:

5.times do |i|
  puts "#{i}: Hello, World!"
end

上面代码输出结果如下 -

irb(main):045:0> 5.times do |i|
irb(main):046:1*   puts "#{i}: Hello, World!"
irb(main):047:1> end
0: Hello, World!
1: Hello, World!
2: Hello, World!
3: Hello, World!
4: Hello, World!
=> 5
irb(main):048:0>

.gsub在找到的字符串中传递。 尝试这个(用括号表示法):

irb(main):048:0> "this is a sentence".gsub("e"){|letter| letter.upcase}
=> "this is a sEntEncE"
irb(main):049:0>

在上面结果中看到gsub正在使用块的结果作为原始匹配的替换。

7.数组

通常当编写程序时,我们需要处理数据的集合。先来看看最常见的数据集合 - 数组。

可视化模型

数组是数字索引列表。 想象一下,有一张空白的纸,画了三个小盒子:

 ---  ---  ---
|   ||   ||   |
 ---  ---  ---

可以按照从左到右对每一个位置进行编号:

 ---  ---  ---
|   ||   ||   |
 ---  ---  ---
  0    1    2

然后在每个框中放入字符串(或其它值):

 -------------  ---------  ----------
| "Breakfast" || "Lunch" || "Dinner" |
 -------------  ---------  ----------
       0            1           2

现在变成一个有三元素的数组。 Ruby数组的大小可以增长和缩小,所以如果添加一个元素,它通常会在结束位置添加,索引值也会变递增1

 -------------  ---------  ----------  -----------
| "Breakfast" || "Lunch" || "Dinner" || "Dessert" |
 -------------  ---------  ----------  -----------
       0            1           2           3

请注意,最后一个元素的位置总是比元素的数量小1

数组中在索引为2位置对应的数据值为“Dinner”。最后一个元素对应的数据值为“Dessert”。

代码中的数组

以下是Ruby代码中相同建模的方法:

irb(main):049:0> meals = ["Breakfast", "Lunch", "Dinner"]
=> ["Breakfast", "Lunch", "Dinner"]
irb(main):050:0> meals << "Dessert"
=> ["Breakfast", "Lunch", "Dinner", "Dessert"]
irb(main):051:0> meals[2]
=> "Dinner"
irb(main):052:0> meals.last
=> "Dessert"
irb(main):053:0>

在上面代码运行结果中,观察到...

  • 该数组是通过将数据片段放在方括号([])之间并用逗号分隔来创建的。

  • 通过使用“铲子运算符”(<<)添加一个元素到数组的末尾

  • 通过使用方括号([])在指定索引位置来获取元素

  • 数组中一些方便的方法,如.last

常用数组方法

数组有很多很酷的东西。 以下是几个例子:

.sort方法

sort方法将返回一个新的数组,其中元素是已经被排序过了。 如果元素是字符串,它们将以字母顺序返回。 如果它们是数字,它们将按升值顺序回来。尝试下面示例:

irb(main):056:0> array1 = ["this", "is", "an", "array"]
=> ["this", "is", "an", "array"]
irb(main):057:0> array1.sort
=> ["an", "array", "is", "this"]
irb(main):058:0> array1
=> ["this", "is", "an", "array"]
irb(main):059:0>

可以使用sort方法重新排列元素的顺序。使用each方法遍历每个元素。使用join方法将它们一起混合成一个字符串。使用index方法找到特定元素的地址。可以使用include?方法询问数组是否包含指定的元素。

使用数组只要需要一个列表,其中元素是以特定的顺序排序的。

其他的尝试

在数组上尝试下面这些常见的方法:

  • each
  • collect
  • firstlast
  • shuffle

可以参考这个文档了解更多详细信息:http://www.ruby-doc.org/core-2.1.2/Array.html

8.哈希

哈希是数据的集合,哈希中的数据的每个元素是按名称来寻址。作为一个比喻,想一下冰箱。 如果要跟踪放在冰箱内的东西,我们并不关心它的放在哪里 - 顺序并不重要。 相反只是按名称去组织这些东西。如名称“apples”可能具有值3,则名称“oranges”可能具有值1,并且“carrots”值为12。 在本示例中,就可使用哈希。

键/值对

哈希是无序的集合,其中数据被组织成“键/值对”。 哈希的语法更复杂,需要一些习惯:

irb(main):001:0> produce = {"apples" => 3, "oranges" => 1, "carrots" => 12}
=> {"apples"=>3, "oranges"=>1, "carrots"=>12}
<e are #{produce['oranges']} oranges in the fridge."
There are 1 oranges in the fridge.
=> nil
irb(main):003:0>

键用作为地址,值是该地址的数据。 在produce哈希中有包括“apples”和“oranges”的键,其值分别为123。当创建哈希时,键和值使用=>符号链接。 所以哈希从一个大括号{开始,(由一个键,一个=>标识符和一个由逗号分隔的值组成的零个或多个条目,然后以一个关闭的大括号}结束。

再尝试一些代码:

irb(main):006:0> produce["grapes"] = 219
=> 219
irb(main):007:0> produce
=> {"grapes"=>219}
irb(main):008:0> produce["oranges"] = 66
=> 66
irb(main):009:0> produce
=> {"grapes"=>219, "oranges"=>66}
irb(main):010:0> produce.keys
=> ["grapes", "oranges"]
irb(main):011:0> produce.values
=> [219, 66]
irb(main):012:0>

在这些说明的第一行中,向哈希添加了一个新值。 由于“grapes”键不在原始哈希中,所以它的值为221。 哈希中的键必须是唯一的,所以当对product [“oranges”]使用相同的语法时,它会看到键“oranges”已经在列表中,并且用6替换值。keysvalues方法会列出所有键和值。

简化哈希语法

通常会使用符号作为哈希的键。 当所有的键都是符号时,可以使用一个速记语法:

irb(main):012:0> produce = {apples: 3, oranges: 1, carrots: 12}
=> {:apples=>3, :oranges=>1, :carrots=>12}
irb(main):013:0> puts "There are #{produce[:oranges]} oranges in the fridge."
There are 1 oranges in the fridge.
=> nil
irb(main):014:0>

请注意,键以冒号结尾,而不是以冒号开始,即使这些是符号。 这个简化的语法能在Ruby 1.9及更高版本配合使用。要了解正在使用的是哪个版本的Ruby,可在控制台中输入“ruby -v”。

9. 条件

条件语句评估求值结果为truefalse。 最常见的条件运算符是==(相等),>(大于),>=(大于或等于),<(小于)和<=(小于或等于)。

一些对象也有返回truefalse的方法,因此它们在条件语句中使用。 例如,每个对象都有方法.nil? 只有当对象为nil时才返回:true。 数组有一个名称为.include的方法 如果数组包含指定的元素,则返回true。 Ruby中的约定方法名称以结尾返回truefalse

条件分支/指令

为什么要有条件语句? 最常见的是控制条件指令,特别是:if/elsif/else结构。在IRB中添加一个这样的方法来写一个例子:

def water_status(minutes)
  if minutes < 7
    puts "The water is not boiling yet."
  elsif minutes == 7
    puts "It's just barely boiling"
  elsif minutes == 8
    puts "It's boiling!"
  else
    puts "Hot! Hot! Hot!"
  end
end

# run method with difference parameter
water_status(5)
water_status(7)
water_status(8)
water_status(9)

尝试使用:water_status(5)water_status(7)water_status(8)water_status(9)运行该方法。

理解执行流程

minutes值为5时,执行结果是什么?因为minutes = 5小于7,所以打印出来的结果为:“The water is not boiling yet.

minutes值为7时,执行结果是什么?因为minutes值等于7,所以打印出来的结果为:“It's just barely boiling

minutes值为8时,执行结果是什么?因为minutes值等于8,所以打印出来的结果为:“It's boiling!

minutes值为9时,执行结果是什么?因为minutes = 9,它比较了前面的几个值:578,但是都没有匹配项,所以最后执行到else语句块中,打印出来的结果为:“Hot! Hot! Hot!

if语句可能的结构

if语句有以下可能的结构:

  • if语句的指令只有在语句为真时执行。
  • if语句后面可有零或多个elsif语句,其指令仅在语句为真时执行
  • if语句后面零或一个else语句,如果没有一个ifelsif语句为真,则执行else语句中的指令。

if/else if/else结构中只能在一个部分可以运行它的指令。例如,如果if是真的,Ruby将永远不会执行elseifelse,也就是说永远只执行其中一块。

相等与分配值

编写条件语句时遇到常见错误是书写===,以及它们的区别。

  • =符号表示赋值。表示“拿右边的东西,把它粘在左边的任何东西”
  • ==表示为这是一个问题。表示“右边的东西是等于左边的东西吗?”

还可以使用逻辑运算符组合条件语句。 最常见的是“逻辑与”和“逻辑或”。 在Ruby中,您可以使用这样的双符号(&&)来书写表示一个“逻辑和”。可以用这样的双管道(||)书写表示一个“逻辑或”。

10. Nil和虚无

什么是虚无? 当我们表达一个东西,没有确定它是什么东西的暂时可以叫它为:虚无,不是没有什么东西吗? 好的,这太多哲学了,这有确实点难解释了。

nil是Ruby中用于表达“虚无”的方式。

如果有三个鸡蛋,您吃三个鸡蛋,那么可能认为现在您“没有什么”蛋了,但是在鸡蛋方面有“0”个。0是什么?它是一个数字,它并不是“虚无”。

如果使用一个单词,如“hello”这样的字符串,那么删除“h”,“e”,“l”和“o”,你可能会认为没有什么,但是现在真的有“”,它是一个空字符串,并不是“虚无”。

nil是Ruby的虚无的想法的表示。 当要求不存在的东西时,通常会遇到这种情况。 例如,当查看数组时,创建了一个包含五个元素的列表,然后要获取列表中添加第六个元素。但是没有第六个元素,所以Ruby给了nil。 在第六个元素的地方它并不是空白(“”),也不是数字0,它是空/nil

编写Ruby代码时遇到的大部分错误是涉及nil值的。以为某个位置有数据值,试图使用使用这个数据值去做一些事情,但没有这样的数据值,不能做任何事情,所以Ruby引发了一个错误。

11. 对象,属性和方法

Ruby是面向对象的编程语言

Ruby是一种面向对象的编程语言,在与VM内部交互的所有东西都是对象。 每条数据都是一个对象。 对象保存的信息称为属性,可以执行对象的方法。

作为一个对象的例子,想像你是一个人。 你有像高度,重量和眼睛颜色的属性。 你有“走路”,“跑步”,“洗碗”和“白日梦”的方法。不同类型的对象具有不同的属性和方法。 在接下来的章节中,将介绍一些Ruby中常见的特定类型的对象。

类和实例

在面向对象编程中,我们定义了类,它们是类别或类型的东西的抽象描述。 它定义了该类型的所有对象的属性和方法。

定义一个类

例如,考虑对一个学校信息建模。要创建一个名为“Student”的类,表示学生的抽象。 Student类将定义如:first_namelast_nameprimary_phone_number的属性。 它可以定义一个用于学生自我介绍的方法:introduction

尝试在IRB编写上面代码:

class Student
  attr_accessor :first_name, :last_name, :primary_phone_number

  def introduction
    puts "Hi, I'm #{first_name}!"
  end
end

attr_accessor方法是用于定义类的实例的属性。

创建类的实例

Student类本身不代表学生,这是学生信息表示模型。 要表示一个实际的学生,需要创建一个Student类的实例。

想像你就是一个学生,不是一个抽象的概念,因为你是一个实际的人。这个实际的人是Student类的一个实例 - 它是一个抽象思想的实现。一个实际的人具有属性:first_namelast_nameprimary_phone_number 的实际数据(比如:你的first_name是“爱华”,last_name是“”等等)。

另一方面,Student类有几个抽象的属性: first_namelast_nameprimary_phone_number,我们不能提前确定它们。

从文件运行Ruby

一般情况下,很少在IRB中定义类。这是因为IRB只是一个便签本(不能很好的保存代码),记得吗? 下面来看看如何从文件中运行Ruby。

  • 退出IRB会话(输入:exitCtrl + D)
  • 注意终端当前在哪个文件夹,进入你的“工作目录”(本教程中,代码都是写在:F:\worksp\ruby)
  • 使用纯文本编辑器创建一个名为student.rb的文件。
  • 将文件保存在student.rb文件中。
  • 从终端运行文件:
ruby student.rb

由于这个文件是空的,所以不应该得到任何输出。

创建Student

在文本编辑器中,开始编写类的结构:

class Student

end

在类的内部,通常使用def关键字定义一个或多个方法,如下:

class Student
  def introduction
    puts "Hi, I'm #{first_name}!"
  end
end

请注意,puts行正在计算求值一个名为first_name的方法,该方法返回学生的名字。下面可以进一步添加之前使用的三个属性:

class Student
  attr_accessor :first_name, :last_name, :primary_phone_number

  def introduction
    puts "Hi, I'm #{first_name}!"
  end
end

运行文件

回到终端,尝试用ruby student.rb运行文件。应该不会看到有结果输出。

这是为什么呢? 上面步骤中已经定义了一个Student类,并表示一个学生有一个名为introduction的方法以及一些属性 - 但是实际上并没有创建Student类的实例或调用任何方法。

创建实例

当定义一个类后,还要创建类的一个实例,如下所示:

frank = Student.new

Student类上调用new方法并将其存储到变量frank中。当有了这个类的实例以后,就可以调用实例的方法来设置或获取其属性。

使用以下语法调用方法:object.method_name。在上面示例中,创建一个实例变量:frank,现在可以通过调用 frank.introduction 来获取学生的介绍信息了。

在文件中创建一个实例

student.rb文件的底部,在Student类的end关键字之后,添加以下内容:

frank = Student.new
frank.first_name = "Frank"
frank.introduction

最终完整的代码如下所示 -

class Student
  attr_accessor :first_name, :last_name, :primary_phone_number

  def introduction
    puts "Hi, I'm #{first_name}!"
  end
end

frank = Student.new
frank.first_name = "Max"
frank.introduction

保存代码并返回到终端,再次执行ruby student.rb。 现在应该输出:“Hi, I'm Max!

方法参数

有时,方法使用一个或多个参数来完成一些事情。 例如,可以调用 frank.introduction('Minlee'),让它向Minlee介绍自己。参数可以是数字,字符串或任何种类的对象,下面修改introduction方法,以使用一个参数:

class Student
  attr_accessor :first_name, :last_name, :primary_phone_number

  def introduction(target)
    puts "Hi #{target}, I'm #{first_name}!"
  end
end

frank = Student.new
frank.first_name = "Maxsu"
frank.introduction('Minlee')

保存代码并返回到终端,再次执行ruby student.rb。 现在应该输出:“Hi Minlee, I'm Maxsu!

返回值

在Ruby中,每次调用方法时都会得到一个值。 默认情况下,Ruby方法返回其评估求值的最后一个表达式的值。

现在向Stuent类中添加一个方法:favorite_number,如下所示 -

class Student
  attr_accessor :first_name, :last_name, :primary_phone_number

  def introduction(target)
    puts "Hi #{target}, I'm #{first_name}!"
  end

  def favorite_number
    7
  end
end

frank = Student.new
frank.first_name = "Maxsu"
puts "Maxsu's favorite number is #{frank.favorite_number}."

打开终端运行上面代码,应该看到:“Maxsu's favorite number is 7”。文件的最后一行调用的是favorite_number方法。 该方法的最后一行(只有)行是第7行。这个表达式作为方法的返回值,该值返回给调用该方法的任何人。在例子中,这7数字值返回并被插入到字符串中。

注意:写在最后,需要注意的是:这篇教程包教不包会!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,577评论 18 399
  • 第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型...
    大学一百阅读 3,211评论 0 4
  • 被失望 真的很令人沮丧 是我不在美好了 导致形象崩塌了 所以越来越讨人厌 连自己都不喜欢自己 别人又怎么会喜欢呢 ...
    一只带眼镜的熊阅读 175评论 1 0
  • 在xml文件中,书写TabLayout和ViewPager标签 ViewPager的适配器 新建Fragment ...
    sun_wenming阅读 795评论 0 1
  • 今天一大早就去同仁医院等待从哈尔滨来的闺蜜级好友,她带妈妈来看眼病,我通过同仁医院的朋友帮她约了国内最顶尖的专家,...
    火种格格阅读 293评论 0 1