第一章 导言
-
Ruby是完全面向对象的。
-
Ruby的注释以“#”开头。
-
Ruby在调用无参数方法的时候,通常省略括号;而且Ruby只能通过方法访问对象的内部状态。
-
代码块和迭代器
1) times和upto是整数对象实现的方法,是一种被称为“迭代器(iterator)”的方法,类似于循环。“{}”中包含的代码成为代码块(block)。3.times {print "Ruby! "} 1.upto(9) {|n| print n}
2) 数组(以及类似的“可枚举的”对象)具有名为each的迭代器,它为每个元素调用一次相关联的代码块;每次对代码块的调用都以该元素作为参数。
a = [1, 2, 3] a.each do |n| print n ** 2 end
3)其他迭代器
- map 用于遍历数组中的元素,执行代码块中的操作,并将代码块的返回值置于map所返回的新数组中。
- select 用于遍历数组中的元素,执行代码块中的操作,如果返回判断为true,则将该元素置于select所返回的新数组中。
inject也都是a = [1, 2, 3, 4] b = a.map {|n| n ** 2} # b = [1, 4, 9, 16] c = a.map {|n| print n} # c = [nil, nil, nil, nil] d = a.select {|n| n % 2 == 0} # d = [2, 4] e = a.select {"k"} # e = [1, 2, 3, 4] f = a.select {|n| print n} # f = []
4) 哈希(hash)也是Ruby的基础数据结构。与数组类似,以“[]”来存取元素值,不过hash是以键对象来作为索引。
Hash类也定义了each迭代方法,此方法为每个键值对调用一次代码块,并将键和值作为参数传入代码块。
Hash可以使用任何对象作为键,但是Symbol对象是最常用的。
k = "key 01" h = { :one => 1, :two => 2, k => "Value 01" } h[:one] = "ONE" p "h[k]=> '#{h[k]}'" h.each do |k, v| p "#{k}: #{v}" end
-
字符串内插:双引号中可以包含任何ruby表达式,但这些表达式必须包含在分界符#{和}里。表达式的值通过to_s方法,转化为字符串代替原表达式。
p "#{true}" # 打印出"true" p "#{false}" # 打印出"false" p "#{nil}" # 打印出""
-
表达式和操作符
1)Ruby的语法是面向表达式的,诸如if类的控制结构其实也是表达式,也是具有值的。就很像三目运算符。m = if 2 > 1 then "y" else "n" end
2)虽然Ruby所有语句都是表达式,但是并不是所有的语句都会返回有意义的值。比如while循环和方法定义通常都只返回nil。
3)许多Ruby操作符都是作为方法来实现的,而且类可以从定义它们。但是不能定义全新的操作符,因为可识别的操作符是一个固定的集合。
"Ruby! " * 3 # "Ruby! Ruby! Ruby! " "Hello, %s! -- %d" % ["Ruby", 2011] # "Hello, Ruby! -- 2011" [1,2,3] << 5 # [1, 2, 3, 5] "Hello, " << "Wolrd!" # "Hello, Wolrd!"
4)[]是可以被重写的最为强大的操作符之一。Array类的[]操作符就可以接受两个参数,用来获取数组的子数组或者片段。
-
方法
1)def定义,返回最后一个表达式的值
def cube(x) x ** 3 end
2)如果定义在类或模块之外,则是一个全局函数,而不是一个方法。全局函数实际可以认为是Object类的私有方法。
3)可以为类或对象专门定义方法,只要以类名或对象名为前缀即可。
a = "Solana" def a.say() p "I'm Solana!" end a.say
-
赋值
1) 并行赋值
x, y, z = 1, 3, 5 # x=1; y=3; z=5 x, y = y, x # 交换值 a, b, c = [2, 4, 6] # a=2; b=4; c=6
2)方法可以有多个返回值,并行赋值很方便
def calc(x) [x**2, x**3] end a, b = calc(7) p a, b
3) 以等号结尾的方法,Ruby允许以赋值操作的语法来调用它们。
o.x=(1) o.x = 1
-
前缀后缀标点符号
1)后缀
后缀?的方法,表示谓词,返回Boolean值;比如Array的empty?方法。
不带!的方法,返回调用该方法的对象的一个修改过的拷贝;后缀!的方法,则是一个可变方法,可以修改原对象。比如Array的sort和sort!方法。
a = [] b = [4,7,2,3,9,1] c = b p a.empty? b.sort p b b.sort! p c
2)前缀
$ 全局变量
@ 实例变量
@@ 类变量
-
RegExp和Range都有字面量,都定义了==操作符来进行相等性测试,也都定义了===操作符来进行匹配性和从属性测试。
x = 3 p case x when 0...3: "0 <= x < 3" when 3...6: "3 <= x < 6" when 6..9: "6 <= x <= 9" else "others" end usrname = "Gengv2007" p case usrname when /^[a-z]/ "Started with lowercase letter." when /^[A-Z]/ "Started with uppercase letter." when /\d$/ "Started with number." end
Ruby的case语句看起来是“非直落”的。
-
类是一些相关方法的集合,这些方法操作一个对象的状态,一个对象的状态被保存在它的实例变量中(@开头的变量)。
-
Ruby的字符串是可变的,[]=操作符可以改变字符串中的字符,或者插入、删除、替换子字符串;<<操作符可以再字符串后面追加内容。
-
字符串是可变的,所以再循环中包含一个字符串字面量,每次循环都会为它创建新的对象。通过在字符串(或其他任何对象)上调用freeze方法,可以防止对该对象的任何改变。
-
条件和循环(如if、while)的判断表达式不一定非得是true或false;nil被当成false来处理,其他任何值(比如0或者"")都被当成true。