1. 标准类型


1.1 数字

Ruby支持整数和浮点数。整数可以是任何长度,一定范围内的整数在内部以二进制形式存储,它们是Fixnum类的对象,范围之外的整数存储在Bugnum类的对象中。Ruby会自动管理它们之间的来回转换。

在书写整数时,可以使用一个可选的前导符号,可选的进制指示符(0b表示二进制,0表示八进制,0d表示十进制,0x表示十六进制),后面跟一趾符合适当进制的数字,下划线在数字串中被忽略。

带有小数点或幂的的数字字面量被转换成浮点对象,必须在小数点之前和之后都给出数字,比如"1.0e3"写成"1.e3",Ruby会试图调用Fixnum类的e3方法。

整数也支持几种迭代器,比如times表示次数,例如:

6.times {puts '-'}

还有upto和downto,它们在两个整数之间分别向上和向下迭代,例如:

1.upto(10) {|i| puts i}
10.downto(1) {|i| puts i}

Numeric类提供了更通用的step方法,例如:

1.step(100, 10) {|i| puts i}


1.2 字符串

Ruby字符串是8比特字节的序列,通常它们包含可打印字符,但这不是一个必要条件,字符串也可以包含二进制数据,字符串是String类的对象。

可以在字符串字面量中放置各种转义序列,例如"\n",表示一个回车换行符。除此之外,可以使用"#{}"序列把任何Ruby代码的值放进字符串中,如果代码只是全局变量、类变量或实例变量,花括号可以忽略。

另外还有3种方式去构建字符串字面量。"%q"和"%Q"分别开始界定单引号和双引号的字符串,例如:

%q/Hello World!/
%Q/Hello #{name}/

跟在q或Q后面的字符是分界符,字符串被一直读取直到发现相匹配的结束符号,否则,字符串会被一直读取,直到出现下一个相同的分界符。

最后,可以使用"here document"构建字符串,例如:

string = < 
  

"here document"由源文件中的那些行但没有包含在"<<"字符后面指明终结字符串的行组成,如果把一个减号放在"<<"字符后面,就可以缩进编排终结符,例如:

string = <<-END_OF_STRING
  Hello World!
  Hello John!
  END_OF_STRING

Ruby有75个以上的标准方法,比如String#chmop方法可以去除首尾空格,例如:

puts "Hello World!\r\n".chomp

String#split方法可以根据正则表达式分割字符串,例如:

stringlist = 'Hello John!'.split(/ /)
puts stringlist[1]

String#squeeze方法可以删除重复字符,例如:

puts 'Hello World!!!'.squeeze('!')

String#scan方法从字符串中抽取匹配正则表达式的元素,例如:

puts 'Hello World!'.scan(/e.*l/)


1.3 区间

区间的第一个且可能最自然的用法是表达序列,在Ruby中使用".."和"..."区间操作符来创建序列。两个点的形式是创建闭合的区间,而3个点的形式是创建半闭半并的区间(不包括右端的值)。可以使用to_a方法把区间转换成数组,例如:

(1..10).to_a
('bar'..'bat').to_a

区间实现了许多方法可以迭代它们,并且以多种方式测试它们的内容,例如:

digits = 0..9
digits.include?(5)
digits.min
digits.max
digits.reject {|i| i<5}
digits.each {|digit| dial(digit)}

Ruby可以根据自己所定义的对象来创建区间,唯一的限制是这些对象必须返回在序列中的下一个对象作为对succ的响应,而且这些对象必须是可以使用"<=>"来比较的,"<=>"操作符比较两个值,并根据第一个值是否小于、等于或大于第二个值,分别返回-1,0或+1,例如:

class Test
  include Comparable
  attr :value
  def initialize(value)
    @value = value
  end
  def <=>(other)
    self.value <=> other.value
  end
  def succ
    Test.new(@value.succ)
  end
end
myvalue = Test.new(1)..Test.new(9)
myvalue.to_a
myvalue.include?(Test.new(2))

区间可以当作条件表达式来使用,当区间第一部分的条件为true时,它们就打开,当区间第二部分的条件为true时,它们就关闭,例如:

while line = gets
  puts line if line =~ /start/ .. line =~ /end/
end

区间还有一种用法是间隔测试,看一些值是否会落入区间表达的间隔内,使用"==="操作符即可,例如:

(1..10) === 5


1.4 正则表达式

正则表达式被用来根据模式对字符串进行匹配。Ruby提供了内建的支持,使得匹配和替换更方便和更简明。正则表达式是Regexp类型的对象,可以通过显示调用构造函数或使用字面量形式"/pattern/"和"%r{pattern}"来创建它们,例如:

Regexp.new('^[a-z]+')
/^[a-z]+/
%r{^[a-z]+}

有了正则表达式对象,可以使用Regexp#match或匹配操作符"=~"和"!~"对字符串进行匹配。匹配操作符对String和Regexp对象均有定义,例如:

name = 'John'
name =~ /o/
/a/ =~ name

匹配操作符返回匹配发生的字符位置,它们会设置一些Ruby变量。"$&"得到与模式匹配的那部分字符串,"$`"得到匹配之前的那部分字符串,而"$'"得到匹配之后的那部分字符串。

每个正则表达式包含一种模式,用来对字符串进行正则表达式的匹配。在特殊字符之前放置一个反斜线便可以匹配它们的字面量。


2. 方法


2.1 定义方法

可以使用关键字def来定义一个方法。方法名必须以一个小写字母开头。表示查询的方法名通常以"?"结尾,例如instance_of?。会修改接收者对象的方法,可以用"!"结尾,例如chop和chop!,第一个方法返回一个修改后的字符串,而第二个则就地修改对象。可以被赋值的方法以一个等号"="结尾。

方法可能还需要声明某些参数,它们就是括号中列出的局部变量。方法参数两边的括号是可选的,例如:

def method1(arg1, arg2, arg3)
end
def method2
end

Ruby可以指定方法参数的默认值,例如:

def method(arg='John')
end

如果希望传入可变个数的参数或者用一个形参接收多个参数,在参数名前放置一个星号"*"即可,例如:

def method(*arg) 
end

当调用一个方法时,可以用一个block与之相关联,通常可以使用yield从方法内部调用这个block。但是如果方法定义的最后一个参数前缀为"&",那么所关联的block会被转换为一个Proc对象,然后赋值给这个参数,例如:

def method(&block)  
  block.call()
end
method() {puts "Hello World!"}


2.2 调用方法

可以通过指定接收者、方法的名称、可选的参数及block,来调用一个方法。对类方法或模块方法来说,接收者是类或模块的名字。如果省略了接收者,其默认是self。 每个被调用的方法都会返回一个值。Ruby有一个return语句,可以从当前执行的方法中退出,如果不需要return,则返回的是方法执行中最后一个语句执行的结果。

在方法定义中,如果在一个正规参数前加上星号,那么传入这个方法调用的多个参数将会被装入一个数组。如果要分解一个数组,则在数组参数前加一个星号"*",例如:

def method(args1, args2, args3)
  puts "#{args1} #{args2} #{args3}"
end
method(1, 2, 3)
method(1, *[2, 3])