运算符 | 说明 |
---|---|
+ | |
- | |
* | |
/ | |
% | |
** | 求幂 |
== | |
=== | ???case..when语句中使用,一般不在外部使用??? |
!= | |
> | |
< | |
>= | |
<= | |
<=> | 返回参数比较的结果,0/1/-1 |
= | |
+= | |
-= | |
*= | |
/= | |
%= | |
**= | |
& | |
| | |
^ | 异或 |
~ | 取反 |
>> | |
<< | |
&& | ???同and??? |
|| | ???同or??? |
! | ???同not??? |
and | |
or | |
not | |
? : | |
. | Array.size |
.. | 1..5 ==> 1-5 |
… | 1…5 ==> 1-4 |
:: | Net::HTTP |
2. 一些判断的方法
eql?——判断值对象是否相等
equal?——判断对象ID是否相等
defined?
```
#判断变量是否定义
foo = 42
defined? foo # => "local-variable"
defined? $_ # => "global-variable"
#判断方法是否定义
defined? puts # => "method"
defined? puts(bar) # => nil (bar is not defined here)
defined? unpack # => nil (not defined here)
#判断块是否被传递
defined? yield # => "yield" (if there is a block passed)
defined? yield # => nil (if there is no block)
```
3. 运算符重载
不能被重载的运算符
= .. … ?: :: && || not and or
重载二元运算符
重载二元运算符时,常把参数名定义为other
在方法内创建当前类的对象时,不能直接写类名,因为直接写类名会创建确定的类,而用self.class,创建的类就是实际调用new方法时的类
class Point
attr_reader :x, :y
def initialize( x = 0, y = 0 )
@x, @y = x, y
end
def inspect
"#{x}, #{y}"
end
def +(other)
self.class.new( x + other.x, y + other.y )
end
def -(other)
self.class.new( x - other.x, y - other.y )
end
end
point0 = Point.new(3, 6)
point1 = Point.new(1, 8)
p point0 #==> 3, 6
p point1 #==> 1, 8
p point0 + point1 #==> 4, 14
p point0 - point1 #==> 2, -2
作为程序运行结果输出,用to_s方法;内部调试时,用inspect方法
重载一元运算符
可以重载的一元运算符:+ - ~ !
重载时,以+@ -@ ~@ !@命名
class Test
def -@
self.class.new(-x, -y)
end
end
重载下标方法
class Point
def [](index)
case index
when 0
x
when 1
y
else
p "Error"
end
end
def []=(index, val)
case index
when 0
self.x = val
when 1
self.y = val
else
p "Error"
end
end
end
point = Point.new(3, 6)
p point[0] #==> 3
p point[1] = 2 #==> 2
p point[1] #==> 2
p point[2] #==> 错误
异常处理
begin
可能会发生异常的处理
rescue => ex #异常对象
发生异常时的处理
ensure
不管是否发生异常都希望之星的处理
end
发生异常时被自动赋值的变量
$!——最后发生的异常(异常对象)
$@——最后发生异常的位置信息
异常对象的方法
class——异常的种类
message——异常消息
backtrace——$@ == $!.backtrace
简写
# 如果整个方法或类都捕获异常的话,可以省略begin~end,直接写rescue或ensure部分
def foo
process
rescue
异常处理
ensure
后处理
end
重试
begin
process
rescue
sleep 10
retry #==> 发生异常时,重复执行process
end
rescue修饰符
表达式1 rescue 表达式2
如果表达式1发生异常,表达式2的值会成为整体表达式的值,等价于
begin
表达式1
rescue
表达式2
end
指定需要捕获的异常
用多个rescue分开处理
begin
process1
rescue Exception1, Exception2 => 变量1
process2
rescue Exception3, Exception4 => 变量3
process3
rescue => 变量3
process4
end
异常类
Exception
|
|==========SystemExit
|==========NoMemoryError
|==========SignalException
|==========ScriptError
|==========|==========LoadError
|==========|==========SyntaxError
|==========|==========NotImplementedError
|==========StandardError
|==========|==========RuntimeError
|==========|==========SecurityError
|==========|==========NameError
|==========|==========|==========NoMethodError
|==========|==========IOError
|==========|==========|==========EOFError
|==========|==========SystemCallError
|==========|==========|===============Errno:EPERM
|==========|==========|===============Errno:ENOENT
程序默认捕获StandardError类及其子类的异常
自己定义异常时,一般先定义继承StandardError的新类,然后再继承这个类
MyError = Class.new(StandardError)
MyError1 = Class.new(MyError)
MyError2 = Class.new(MyError)
MyError3 = Class.new(MyError)
MyError4 = Class.new(MyError)
begin
process
rescue
process1
end
主动抛出异常
raise 方法——主动抛出异常
raise message
抛出RunTimeError异常,把message传给异常对象
raise 异常类
抛出指定的异常
raise 异常类,message
抛出指定的异常, 把message传给异常对象
raise
在rescue外时,抛出RunTimeError
在rescue中时,再次抛出最后一次发生的异常
块就是在调用方法时,能与参数一起传递的多个处理的集合
块的使用
循环
实现了循环处理的方法,称为迭代器
sum = 0
hash = { "a"=>1, "b"=>2, "c"=>3, "d"=>4 }
hash.each do |pair|
sum += pair[1] #==> 用pair表示散列,pair[0] = key, pair[1] = value
end
hash.each do |key, value|
sum += value
end
隐藏常规处理
#确保后处理被执行
File.open("XXX") do |file|
file.each_line do |line|
print line
end
end
#如果open失败,open方法会自动调用close,不用手动close
替换部分算法
array = ["Ruby", "Perl", "Python", "PHP"]
sorted = array.sort
p sorted #==> ["PHP", "Perl", "Python", "Ruby"]
array = ["Ruby", "Perl", "Python", "PHP"]
sorted = array.sort{ |a, b| a <=> b } #==> 将负责比较的块变量传递给sort方法
p sorted #==> ["PHP", "Perl", "Python", "Ruby"]
ary = %w(
Ruby is a open source programming language with a focus on simplicity and productivity. It has an elegant syntax that is natural to read and easy to write
)
call_num = 0
sorted = ary.sort do | a, b |
call_num += 1
a.length <=> b.length
end
p "排序结果 #{sorted}"
p "数组的元素数量 #{ary.length}" #==> "数组的元素数量 28"
p "调用块的次数 #{call_num}" #==> "调用块的次数 91"
#用sort_by方法将每个元素在块中调用一次,然后根据结果做排序处理
sorted = ary.sort_by{ |item| item.length }
p sorted
定义带块的方法
执行块
def myloop
while true
yield
end
end
传递块参数,获取块的值
def total(from, to)
result = 0
from.upto(to) do | num |
if block_given? #==> 判断是否有块参数传递进来
result += yield(num)
else
result += num
end
end
return result
end
p total(1, 10) #==> 55
p total(1, 10){ |num| num ** 2} #==> 385
def block_args_test
yield()
yield(1)
yield(1, 2, 3)
end
p "通过|a|接收块变量"
block_args_test do |a|
p [a]
end
#==> [nil]
#==> [1]
#==> [1]
p "通过|a, b, c|接收块变量"
block_args_test do |a, b, c|
p [a, b, c]
end
#==> [nil, nil, nil]
#==> [1, nil, nil]
#==> [1, 2, 3]
p "通过|a|接收块变量"
block_args_test do |*a|
p [a]
end
#==> [[]]
#==> [[1]]
#==> [[1, 2, 3]]
控制块的执行
n = total(1, 10) do |num|
if num == 5
break
end
num
end
p n #==>nil
#在块中使用break,程序马上返回到调用块的地方,之前的结果会被忽略掉
n = total(1, 10) do |num|
if num % 2 != 0
next 0
end
num
end
将块封装为对象
hello = Proc.new do |name|
p "Hello, #{name}"
end
hello.call("David")
hello.call("Wang")
#将块从一个方法传递给另一个方法时,会通过变量将块作为Proc对象接收
#在方法定义时,如果末尾的参数使用“&参数名”的形式,则自动把块封装为Proc对象
#Proc参数一定要在所有参数之后,也就是方法中的最后一个参数
def total2(from, to, &block)
result = 0
from.upto(to) do |num|
if block
result += block.call(num)
else
result += num
end
end
return result
end
局部变量与块变量
x = 1
y = 1
ary = [1, 2, 3]
ary.each do |x|
y = x #==> x值块的局部变量
#==> 块内部,可以引用外部的局部变量y
end