A.1 拟态方法
puts “hello,world”
这里的 puts 实际上是个方法,完整写法
puts(“hello,world”)
如果加上上下文,就是
self.puts(“hello,world”) 或者 main.puts(“hello,world”)。
由此可知 puts 多半是 Object 的一个实例方法。
去掉括号的写法使得它像个关键字,同时也更为简洁,因此称之为拟态方法。
来自 Camping 的例子:
这里的 R 实际上是一个方法,'/help' 是它的参数,返回值是一个 Class的实例。
-
class Help < R '/help'
-
def get
-
# rendering for HTTP GET...
属性的问题:
-
class MyClass
-
attr_accessor :my_attr
-
def initialize_attributes
-
my_attr = 10 # 应该改写为 self.my_attr = 10 或 @my_attr = 10
-
end
-
end
-
obj = MyClass.new
-
obj.initialize_attributes
-
obj.my_attr # => nil
注意在 initialize_attributes 中的 my_attr 具有二义性,Ruby 将无从判断这是一个局部变量,或者是一个方法,默认会当成局部变量,因此我们需要显式使用 self ,或者直接访问 @my_attr。
A.2 空指针保护
a ||= [] 等效于 a = a || []
很明显,这是Ruby 从 perl 偷师的,就是perl 的短路操作符。
A.3 关于方法参数的技巧
具名参数:又一个从 perl 学来的东西
-
def my_method(args)
-
args
-
end
-
my_method(:a => 'X' , :b => 3, :c => 'Y' ) # => {:c=>"Y", :a=>"X", :b=>3}
-
-
#Ruby 1.9 中引入了一种更为简洁的写法
-
-
my_method(a:'X',b:3,c:'Y')
参数数组和默认值
*操作符可以把多个参数收集到一个数组中;
-
def my_method(*args)
-
args
-
end
-
my_method(1, '2' , 'three' ) # => [1, "2", "three"]
Ruby 也支持如下参数默认值:
-
def my_method(x, y = "a default value" )
-
"#{x} and #{y}"
-
end
-
my_method("a value" ) # => "a value and a default value"
混合使用参数的惯用法
-
def my_method(*args)
-
args
-
end
-
my_method(:x, :y => 1, :z => 'A' ) # => [:x, {:y=>1, :z=>"A"}]
A.4 Self Yield
给方法传入一个块时,可以使用 Yield 回调。对象也可以把自身传递给块 。
来自 RubyGems 的例子
-
#传统写法
-
spec = Gem::Specification.new
-
spec.name = "My Gem name"
-
spec.version
-
# ...
-
#Self Yield 写法
-
spec = Gem::Specification.new do |s|
-
s.name = "My Gem name"
-
s.version = "0.0.1"
-
# ...
-
end
-
-
# Gem::Specification 源代码
-
module Gem
-
class Specification
-
def initialize
-
yield self if block_given?
-
# ...
来自 tap() 的例子
-
# Ruby 中,长长的方法调用链很普遍
-
['a' , 'b' , 'c' ].push('d' ).shift.upcase.next # => "B"
-
-
# 但是某一步出错,你将不得不如下调试
-
temp = ['a' , 'b' , 'c' ].push('d' ).shift
-
puts temp
-
x = temp.upcase.next
-
-
# 这非常笨拙;Ruby 1.9 中引入了 tap() 方法,我们可以这样做
-
['a' , 'b' , 'c' ].push('d' ).shift.tap {|x| puts x }.upcase.next
-
-
# 老版本的 Ruby ,我们也可以很容易的实现一个
-
class Object
-
def tap
-
yield self
-
self
-
end
-
end
-
-
# Ruby 很强大吧,缺少某项功能,我们不必坐等软件新版本的发布,我们随时可以增强它。
A.5 Symbol#to_proc() 方法
先看段代码
-
names = ['bob' , 'bill' , 'heather' ]
-
names.map {|name| name.capitalize } # => ["Bob", "Bill", "Heather"]
其实已经很简洁了,可变态的 Ruby 程序员还不甘心,还要可怕的压榨 Ruby。
分析上面代码,无非就是调用 capitalize 。因此诞生了如下写法:
-
names = ['bob' , 'bill' , 'heather' ]
-
names.map(&:capitalize) # => ["Bob", "Bill", "Heather"]
当 & 操作符作用于一个对象时,它会调用该对象的 to_proc 方法,将其转化为一个 proc 对象。
-
&:capitalize.to_proc # 等价于 &::capitalize
看下 to_proc 的实现
-
class Symbol
-
def to_proc
-
Proc.new {|x| x.send(self) }
-
end
-
end
阅读(1451) | 评论(0) | 转发(1) |