如何学习ruby:Ruby 魔法 学习笔记的一

、向对象显示发送消息
我们可以向对象直接发送消息:
Ruby代码
复制代码 代码如下:

HelloWorld
def say(name)
pr "Hello, ", name
end
end
hw = HelloWorld.
hw.send(:say,"world")


我们通常使用hw.say("world")但send可以对private思路方法起作用
不光如此send可以使更加动态下面我们看看个例子:
我们定义了个类Person,我们希望个包含Person对象能够按
照Person任意成员数据来排序:
Ruby代码
复制代码 代码如下:

Person
attr_reader :name,:age,:height
def initialize(name,age,height)
@name,@age,@height = name,age,height
end
def inspect
"#@name #@age #@height"
end
end

在ruby中任何个类都可以随时打开这样可以写出像2.days_ago这样优美
code,我们打开Array并定义个sort_by思路方法:
Ruby代码
Array
def sort_by(sysm)
self.sort{|x,y| x.send(sym) <=> y.send(sym)}
end
end
我们看看运行结果:
Ruby代码
people =
people << Person.("Hansel",35,69)
people << Person.("Gretel",32,64)
people << Person.("Ted",36,68)
people << Person.("Alice", 33, 63)
p1 = people.sort_by(:name)
p2 = people.sort_by(:age)
p3 = people.sort_by(:height)
p p1 # [Alice 33 63, Gretel 32 64, Hansel 35 69, Ted 36 68]
p p2 # [Gretel 32 64, Alice 33 63, Hansel 35 69, Ted 36 68]
p p3 # [Alice 33 63, Gretel 32 64, Ted 36 68, Hansel 35 69]
这个结果是如何得到呢?
其实除了send外还有个地方应该注意attr_reader,attr_reader相当于定义了name,
age,heigh 3个思路方法而Array里sort思路方法只需要提供个比较思路方法:
x.send(sym) <=> y.send(sym) 通过send得到person属性值然后在使用<=>比较
2、定制个object
<< object
ruby不仅可以打开个类而且可以打开个对象给这个对象添加或定制功能而不影响
其他对象:
Ruby代码
a = "hello"
b = "goodbye"
def b.up
gsub(/(.)(.)/)($1.up + $2)
end
puts a.up #HELLO
puts b.up #GoOdBye
我们发现b.up思路方法被定制成我们自己
如果想给个对象添加或定制多个功能我们不想多个def b.method1 def b.method2这么做
我们可以有更模块化方式:
Ruby代码
b = "goodbye"
<< b
def up # create single method
gsub(/(.)(.)/) { $1.up + $2 }
end
def up!
gsub!(/(.)(.)/) { $1.up + $2 }
end
end
puts b.up # GoOdBye
puts b # goodbye
b.up!
puts b # GoOdBye
这个被叫做singleton ,这个是针对b这个对象
和设计模式singleton object类似只会发生东东我们叫singleton.
<< self 给你定义添加行为
Ruby代码
TheClass
<< self
def hello
puts "hello!"
end
end
end
TheClass.hello #hello!
<<self修改了你定义,这是个很有用技术他可以定义级别
helper思路方法然后在这个其他定义中使用下面个列子定义了访问
我们希望访问时候把成员数据都转化成,我们可以通过这个技术来
定义个Class-Level思路方法accessor_:
Ruby代码
MyClass
<< self
def accessor_(*names)
names.each do |name|
_eval <<-EOF
def #{name}
@#{name}.to_s
end
EOF
end
end
end
def initialize
@a = [ 1, 2, 3 ]
@b = Time.now
end
accessor_ :a, :b
end
o = MyClass.
puts o.a # 123
puts o.b # Fri Nov 21 09:50:51 +0800 2008
通过extend module给你对象添加行为,module里面思路方法变成了对象里面
例子思路方法:
Ruby代码
module Quantier
def any?
self.each { |x| true yield x }
false
end
def all?
self.each { |x| false not yield x }
true
end
end
list = [1, 2, 3, 4, 5]
list.extend(Quantier)
flag1 = list.any? {|x| x > 5 } # false
flag2 = list.any? {|x| x >= 5 } # true
flag3 = list.all? {|x| x <= 10 } # true
flag4 = list.all? {|x| x % 2 0 } # false
3、创建个可参数化类:
如果我们要创建很多类这些类只有类成员值区别我们很容易想起:
Ruby代码
IntelligentLe # Wrong way to do this!
@@home_planet = nil
def IntelligentLe.home_planet
@@home_planet
end
def IntelligentLe.home_planet=(x)
@@home_planet = x
end
#...
end
Terran < IntelligentLe
@@home_planet = "Earth"
#...
end
Martian < IntelligentLe
@@home_planet = "Mars"
#...
end
这种方式是实际上Ruby中类成员不仅在这个类中被所有对象共享
实际上会被整个继承体系共享所以我们Terran.home_planet会输出
“Mars”而我们期望是Earth
个可行思路方法:
我们可以通过_eval在运行时延迟求值来达到目标:
Ruby代码
IntelligentLe
def IntelligentLe.home_planet
_eval("@@home_planet")
end
def IntelligentLe.home_planet=(x)
_eval("@@home_planet = #{x}")
end
#...
end
Terran < IntelligentLe
@@home_planet = "Earth"
#...
end
Martian < IntelligentLe
@@home_planet = "Mars"
#...
end
puts Terran.home_planet # Earth
puts Martian.home_planet # Mars
最好思路方法:
我们不使用类变量而是使用类例子变量:
Ruby代码
IntelligentLe
<< self
attr_accessor :home_planet
end
#...
end
Terran < IntelligentLe
self.home_planet = "Earth"
#...
end
Martian < IntelligentLe
self.home_planet = "Mars"
#...
end
puts Terran.home_planet # Earth
puts Martian.home_planet # Mars
4、Ruby中Continuations:
Continuations恐怕是Ruby中最难理解概念了它可以处理非局部跳转
它保存了返回地址和执行环境和c中jmp和longjump类似但它保存
了更多信息:
axgle举曹操例子很形象我们拿过来看看:
来自[http://www.javaeye.com/topic/44271]
曹操(caocao)被誉为“古代轻功最好人 ”“说曹操曹操到”这句名言
在ruby中曹操这种轻功被称为callcc.
Ruby代码
callcc{|caocao|
for say in ["曹操","诸葛亮","周瑜"]
caocao.call say"曹操"
puts say #不会输出曹操已经飞出去了
end
}#“曹操”飞到这里来了(跳出了callccblock紧跟在这个block后面继续执行下面ruby代码)
puts "到"
callcc里caocao是个"延续"(Continuation)对象.这个对象只有名叫“call"这样个思路方法
当执行了caocao.call后caocao就会飞到callcc块(block)后面,让ruby继续执行其下面代码
我上面给出个从块里头”飞“到块外面例子;下面是Programming Ruby给出从代码后面”飞“到代码前面例子:
Ruby代码
arr = [ "Freddie", "Herbie", "Ron", "Max", "Ringo" ]
callcc{|$cc|}#下面$cc.call如果被执行就会飞回到这里(callcc块的后)
puts(message = arr.sht)
$cc.call unless message =~ /Max/
例子大多来自<<The ruby way>>
Tags:  ruby教程 ruby是什么意思 rubyonrails 如何学习ruby

延伸阅读

最新评论

发表评论