Ruby命名规则
变量及方法的命名
局部变量名、方法参数名、方法名都必须以小写字母或者下划线开头。
实例变量名要以“@”作为前缀,如:@quantity
对于包含多个单词的方法名和变量名,Ruby通常用下划线分隔每一个单词(如:line_item),而不是用大写字母(如:lineItem)来分隔。
类、模块及常量的命名
类名、模块名、常量名都必须以大写字母开头,如:Object
对于包含多个单词的类名、模块名、常量名,Ruby通常用大写字母来分隔每一个单词(如:PurchaseOrder),而不是用下划线(如:Purchase_order)来分隔。
符号
Rails使用符号来标识事物。特别是,它在命名方法参数和查找哈希表里的内容时,会把符号作为key(键)来使用。
如:
redirect_to :action => "edit", :id => params[:id]
在这个例子中,符号的示例包括:action和:id。看起来,符号和变量名很像。但和变量名不同的是:符号是以冒号为前缀的。
类和方法的定义
Ruby在定义类和方法的时候,不是使用花括号{}来定义的,而是使用关键字end。如:
def say_goodnight(name)
result = 'Good night, ' + name
return result
end
数据类型
字符串
在Ruby中,用单引号和双引号都可以生成字符串。区别在于:
在输出字符串时,单引号里的所有内容将会原样输出,不会把反斜杠\后的内容识别成为转义字符。而双引号里的反斜杠\后的内容将被识别成为转义字符。
另外,在双引号中括起来的字符串中,还可以插入“#{表达式}”这样的内容,来获取表达式的值。如:
def say_goodnight(name)
"Good night, #{name.capitalize}"
end
这个例子中,#{name.capitalize}将调用capitalize这个方法,得到一个首字母大写的name字符串。
数组
Ruby用方括号[]来创建和初始化一个数组对象,如:
a = [ 1, 'cat', 3.14 ] # array with three elements
下面是访问数组中单个元素的方式:
a[0] # access the first element (1)
a[2] = nil # set the third element
# array now [ 1, 'cat', nil ]
注意:在很多编程语言中,nil或者null意味着“没有对象”。而在Ruby中,nil是对象,只是它代表没有任何东西。
在数组中,常常会使用方法“<<”,来把值追加到其接收器上,如:
ages = []
for person in @people
ages << person.age
end
另外,Ruby在创建以单词为元素的数组时,还可以用下面这种更快捷的方式:
a = [ 'ant', 'bee', 'cat', 'dog', 'elk' ]
# this is the same:
a = %w{ ant bee cat dog elk }
散列(或叫“哈希表”)
Ruby在定义散列的时候,使用的是花括号{}。对于散列中每一个元素,必须包含两个对象:key和value。如:
inst_section = {
:cello => 'string',
:clarinet => 'woodwind',
:drum => 'percussion',
:oboe => 'woodwind',
:trumpet => 'brass',
:violin => 'string'
}
=>的左边是key(如前文所说,在Rails中通常使用“符号”作为key),右边是value。key必须是唯一的。
和数组一样,散列也可以用方括号来索引其中的元素项,如:
inst_section[:oboe] #=> 'woodwind'
inst_section[:cello] #=> 'string'
inst_section[:bassoon] #=> nil
正则表达式
我们可以通过正则表达式来指定要在字符串中匹配的字符模式。在Ruby中,通常使用“/pattern/”或“%R{pattern}”来生成正则表达式。
例如:对于所有包含文本Perl或Python的字符串,可以编写与之相匹配的正则表达式:/Perl|Python/, 它可以改写为/P(erl|ython)/。
而程序通常用匹配运算符“=~”,来判断字符串是否匹配正则表达式。如:
if line =~ /P(erl|ython)/
puts "There seems to be another scripting language here"
end
在字符模式中,可以用“+”和“*”来指定字符串中会重复出现的字符。它们的区别可以用下面这个例子来说明。
/ab+c/:匹配的是以单个字母a开始,紧跟着单个或多个字母b,最后以单个字母c结尾的字符串。
/ab*c/:匹配的是包含单个字母a、零个或多个字母b以及单个字母c的字符串。
正则表达式中最值得注意的几个特殊序列有:
- \d:表示匹配任何数字
- \s:表示匹配任何空白字符
- \w:表示匹配任何包括字母和数字(alphanumerical)的字符
- \A:表示匹配一个字符串的开头
- \Z:表示匹配一个字符串的结尾
- \通配符(如:“.”、“*”等):表示完全按照字符串原样进行匹配
逻辑方法
控制结构
Ruby有常见的控制结构,如if语句和while语句。
- if语句
if count > 10
puts "Try again"
elsif tries == 3
puts "You lose"
else
puts "Enter a number"
end
- while语句
while weight < 100 and num_pallets <= 30
pallet = next_pallet()
weight += pallet.weight
num_pallets += 1
end
和Java等语言不同的是,Ruby不是使用花括号而是使用关键字end来表示一段语句的结束。
Ruby还包含if语句的变种unless语句、while语句的变种until语句。与if和while语句的不同之处就在于:对于unless语句和until语句,当判断条件为假的时候,才会去执行该语句里面的代码。
代码块
Ruby可以用花括号{}或者用“do…end”这两种形式把代码包括起来,来表示那是一个代码块。但通常,花括号用于单行语句的代码块,而do…end用于多行语句的代码块。如:
{ puts "Hello" } # this is a block
do ###
club.enroll(person) # and so is this
person.socialize #
end ###
迭代器
所谓的“迭代器”,实际上就是某种从一个集合(如数组)中返回连续元素的方法。如:
animals = %w( ant bee cat dog elk ) # create an array
animals.each {|animal| puts animal } # iterate over the contents
每一个数组都实现了一个叫作each方法,这个方法可以对数组里的每一个元素进行遍历。
又如:
3.times { print "Ho! " } #=> Ho! Ho! Ho!
每一个整数N都实现了一个叫作times的方法,这个方法可以把一个代码块调用N次。
另外,Ruby可以把代码块传递给某个变量,然后利用“&”这个前缀操作符,以“&变量名”的形式把代码块当作某个方法的参数传递给这个方法。如:
def wrap &b
print "Santa says: "
3.times(&b)
print "\n"
end
wrap { print "Ho! " }
异常
Ruby通过raise这个方法来抛出异常,类似于Java中的throw方法。
当一个异常被抛出后,异常处理机制就接管了程序的运行,并开始寻找一个合适的地方来捕捉这个异常。在Ruby中,捕捉异常用到的是rescue方法,类似于Java中的catch方法。如:
begin
content = load_blog_data(file_name)
rescue BlogDataNotFound
STDERR.puts "File #{file_name} not found"
rescue BlogDataFormatError
STDERR.puts "Invalid blog data in #{file_name}"
rescue Exception => exc
STDERR.puts "General error loading #{file_name}: #{exc.message}"
end
rescue子句可以直接放在方法定义的最外层,并不一定要包含在begin/end块中。
组织结构
类
下面是Ruby类的定义:
1: class Order < ApplicationRecord
- has_many :line_items
- def self.find_all_unpaid
- self.where('paid = 0')
5: end
- def total
- sum = 0
- line_items.each {|li| sum += li.total}
- sum
10: end
- end
- 类名的首字母必须大写。
- 在Ruby类的主体中,带有前缀“self.”的方法是类方法,不带该前缀的方法是实例方法。
- Ruby类的实例方法,默认是public的,任何类的方法都可以去调用它。(而Java类的方法,默认不是public的。在默认情况下,它只能被当前成员所在的类和同一个包里的其他类的方法调用。)
- Ruby的private方法,只能被当前成员所在的类的方法调用。(Java类的private方法也是如此。)
- Ruby的protected方法,只能被当前成员所在的类及其子类的方法调用。(而Java的protected方法,还能被同一个包里的其他类的方法调用。)
模块
除了类,Ruby还有另一种组织结构,就是模块,有关键字module来定义。
模块和类相似,但是,模块不能创建对象。
模块有两个作用:
- 模块可以用来定义方法。
- 模块允许在不同的类之间共享功能。如果多个类混合在同一个模块中,那么它们之间不需要继承,就可以共享模块的功能。
下面是模块的一个示例:
module StoreHelper
def capitalize_words(string)
string.split(' ').map {|word| word.capitalize}.join(' ')
end
end