引用
Ruby is designed to make programmers happy.
Ruby的设计理念就是让开发者用的舒心。先看看Ruby有什么特别之处,感如此自信。
在学习概念之前,得先准备一个环境,好是我能亲身体验。安装环境似乎不是那么容易,简单起见不如用ruby提供的在线解释器:http://tryruby.org/
Ruby Is Object-Oriented - 面向对象
Java说自己是Everything is Object,万事皆对象。Ruby说Everyvalue is Object,每个值都是对象,哪怕是一个数字1,一个布尔变量true,甚至一个空值nil,都是对象。似乎更进一步。
>> 2.class
=> Fixnum
>> 0.0.class
=> Float
>> true.class
=> TrueClass
>> false.class
=> FalseClass
>> nil.class
=> NilClass
上面都是对一些值调用了class方法的执行结果。方法?怎么没有括号?对,省略了,对ruby而言,括号是可选的,尤其是对于无参方法的调用。这真不错,少打两个字符,特别是括号比一般的字符还难打,省力,给力。不过,这里有个问题,不带括号,你怎么知道不是访问的属性?这也是ruby有意而为之的。OO里面不是有封装原则吗?建议不要直接访问对象的属性,而是通过方法来访问,就像POJO。ruby干脆就把这个原则加入到语言级别的限制,而不是设计原则的指导。够霸道!有个性!
Blocks and Iterators - 块与迭代
下面是一个块的例子:
{ puts "Hello" } # this is a block
do ###
club.enroll(person) # and so is this
person.socialize #
end ###
迭代的威力(你会发现很多循环都被迭代实现了,也就是ruby很少用for或while):
>> 3.times { print "Ruby! }
Ruby! Ruby! Ruby! => 3
>> 1.upto(9) {|x| print x }
123456789=> 1
看看上面的代码,这个代码块和循环的实现真实令人耳目一新。
先看迭代,真够简洁,而且接近英语表达。这和我们常用的for和while比起来,简洁多了。其实你想一下,除了循环若干次这种迭代以外,我们还常用哪些迭代?数组!对,数组和Hash就和数字一样也有一些迭代方法,让我们可以循环操作它里面的每个元素。从OO的角度,ruby把迭代这个功能划归给数字,Hash和数组,似乎更为直接。迭代是不是数字,Hash和数组的职责所在呢?在ruby的概念里,是的。
再看这里的代码块。代码块直接跟在对象的方法后面,从而和方法的调用关联起来。这是ruby的一项很强大的基本功能。这种用法常常和循环结合使用,从而达到简洁的表达迭代。
更令人吃惊的是代码块可以作为参数传递(用&表示要传递代码块):
def wrap &b
print "Santa says: "
3.times(&b)
print "\n"
end
wrap { print "Ho! " }
Expressions and Operators - 表达式和操作符
引用
Ruby’s syntax is expression-oriented.
面向表达式的语法。if在java里面是一个语句,但在ruby里面却是一个表达式,表达式是有值的哦:
minimum = if x < y then x else y end
在ruby里面所有的语句都是表达式,但有些没有有意义的返回值,而是返回nil,也就是空。
>> 2 ** 1024
=> 179769313486231590772930519078902473361797697894230657273430081157732
675805500963132708477322407536021120113879871393357658789768814416622492
847430639474124377767893424865485276302219601246094119453082952085005768
838150682342462881473913110540827237163350510684586298239947245938479716
304835356329624224137216
ruby里面的运算和java没有太大的区别,但是ruby的整数是没有大小限制的,这样你就可以再ruby里面表达大数了哦。
Methods
方法用def定义,可以用return 返回值,也可以不用return。没有return的时候,最后一个表达式的值就是返回值。
def square(x)
x*x
end
上面的方法,并没有指明属于哪个类。这叫什么OO啊?其实这样的方法是Object类的私有方法。如果要为一个类定义方法,如下:
def Math.square(x)
x*x # here is comment.
end
这里,Math不仅是一个类,还是ruby内置的类。这又是ruby的一大特色:类和模块是开放的,可以再运行时被修改和扩展。
Indentation & Comment
1. 换行,你不必用分号结束一句话。一条语句占一行
2. 缩进,习惯上ruby喜欢缩进两个字符
3. 块, 用end表示一个代码块的结束。不管是类还是方法,你不需要{}来表示开始和结束
4. 注释,用#表示注释,一直到行末
Data Types
1. 字符串String
这个当然是最基本的类型了。你可以用单引号或者双引号来括起一串字符从而得到一个字符串。但是单引号括起来的字符串ruby基本不做什么处理,而双引号括起来的字符串ruby可以对他做很多事情,比如转移,格式化,正则表达式计算等。
def say_goodnight(name)
"Good night, #{name.capitalize}"
end
puts say_goodnight('pa' )
2. Arrays and Hashes
数组和哈希结构都是带索引的集合,可以存贮任意对象。数组的索引是整数,而哈希的索引可以是任意对象。他们都可以根据需要自动扩展大小。数组的效率更高,而哈希则更为灵活。有趣的是一个数组或哈希集合里面可以存储不同类型的对象。
数组的创建和访问如下:
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 ]
哈希的例子:
inst_section = {
:cello => 'string' ,
:clarinet => 'woodwind' ,
:drum => 'percussion' ,
:oboe => 'woodwind' ,
:trumpet => 'brass' ,
:violin => 'string'
}
inst_section[:oboe] #=> 'woodwind'
inst_section[:cello] #=> 'string'
inst_section[:bassoon] #=> nil
3. Regular Expressions
你可以通过下面的两种方式定义一个正则表达式:
/pattern/ or %r{pattern}
你可以通过=~来测试是否匹配:
if line =~ /P(erl|ython)/
puts "There seems to be another scripting language here"
end
Assignment
除了一般的赋值语法外,ruby还支持很有意思的并行赋值:
x, y = 1, 2 # Same as x = 1; y = 2
a, b = b, a # Swap the value of two variables
x,y,z = [1,2,3] # Array elements automatically assigned to variables
ruby支持多值返回,这得得益于这种并行赋值的强大:
# Define a method to convert Cartesian (x,y) coordinates to Polar
def polar(x,y)
theta = Math.atan2(y,x) # Compute the angle
r = Math.hypot(x,y) # Compute the distance
[r, theta] # The last expression is the return value
end
# Here's how we use this method with parallel assignment
distance, angle = polar(2,2)
Punctuation Suffixes and Prefixes - 前缀与后缀
ruby的方法名似乎没有什么限制,甚至可以有感情色彩,使得编程语言没有那么古板,没有人情味。比如你可以用问好?最为方法名的末尾,这表示返回布尔值,也就是一个谓词判断。比如数组有个方法叫“empty?”。你也可以在名字后面加上谈好!,表示用这个方法的时候要注意。很多ruby的核心类都定义了一套带!和不太!的同名方法,不带!的方法呢不会改变对象的值,带!的则会。
除了后缀,还有前缀。比如$符号开头的代表是全局变量。@开头的是对象实例的变量。@@开头的是类的变量。也就是表达了三个不同的变量作用域scope。
Ruby Names
ruby的命名规则很特别:
1. 本地的变量,方法参数和方法名称都得用小写字母或者下划线开头。对象实例内的变量用@开头。如果名字含有多个单词,就用下划线隔开。order, line_item, xr2000。
2. 类名,模块名和常量,必须用大写字母开头。如果含有多个词,用驼峰结构。Object,
PurchaseOrder, LineItem。
Regexp and Range - 正则表达式和范围
ruby提供了正则表达式对象和从一点到另一点的范围对象。
/[Rr]uby/ # Matches "Ruby" or "ruby"
/\d{5}/ # Matches 5 consecutive digits
1..3 # All x where 1 <= x <= 3
1...3 # All x where 1 <= x < 3
Classes and Modules - 对象和模块
引用
A class is a collection of related methods that operate on the state of an object.
类就是一些方法的集合,这些方法都是用来访问和操作对象状态的。所谓对象的状态,就是指对象的实例变量的值,也就是@开头的那些变量的值。
Ruby Surprises
Ruby的字符串是可变的。你知道java的字符串是不可变哦。
在使用条件表达式估值的地方,比如if,for和while,表达式的值不一定是true或者false哦。nil被看做false,其他的值都被看成是true哦。