Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 417 lines (370 sloc) 16.5 KB
---------------------------------------------------------------------------------------------------------------------------------------------------------
#About objects,instance variables,and methods.
对象的实例变量被存储在对象里面,实例方法通过对象的object_id到对象的class里面查找实例法
#methods()
返回该对象的所有能respond_to?的方法
#instance_methods: (Only instance can use them)
返回该对象的所有public,protected的实例方法
#private method
私有方法只能直接调用方法名而且当前self变量的值必须为其声明的对象值
---------------------------------------------------------------------------------------------------------------------------------------------------------
ruby的module主要用于mixin(解决多重继承的问题)扩展方法和用于命名空间
当需要一个被继承或者能实例化的对象时才用class
module的优劣:?
--------------------------------------------------------------------------------------------------------------------------------------------------------
module MyModule
MyConstant = 'Outer constant'
class MyClass
MyConstant = 'Inner constant'
end
end
静态变量在modules和classes里面存储模式类似于文件夹(modules,classes)与文件(constant)的方式
故在不同文件夹下同名文件也不会冲突。
---------------------------------------------------------------------------------------------------------------------------------------------------------
load() 每次都会重新加载文件,并执行里面的码。
require() 只加载一次,加载的模式相当于import进来一个库。
#当应用load("filename", ture) 时加载进来的文件将放在一个匿名module里面,用完之后销毁匿名modue(目的是阻止加载进入的文件pollute当前class)
---------------------------------------------------------------------------------------------------------------------------------------------------------
对象与类的总结:(注意事项,ruby会打开已定义的类和模块所以在定义新类名和模块名时切忌避免冲突和混乱)
什么是对象?
对象就是指向类的实例变量,在ruby里面一切皆是对象除了:block,method
什么是类?
类即是Class的实例对象,加上一列实例方法和指向一个superclass
classes,Object,BasicObject,Module...的类都是Class,Class类的类是自己
Class是Molule的子类,所以a class is also a module.
---------------------------------------------------------------------------------------------------------------------------------------------------------
当你include一个module到class或module时ruby会创建一个匿名类包含那个module的内容,
then inserts the anonymous class in the chain,just above the including class itself.
---------------------------------------------------------------------------------------------------------------------------------------------------------
self # => main
self.class # => Object
在ruby的顶层空间是main对象(Object的一个实例),他提供顶层执行环境——>意思时ruby所有操作都是在对象内部执行的。
#补充介绍Kernel
Ruby includes some methods, such as print( ), that you can call from
anywhere in your code. they are actually private instance methods of module Kernel.
class Object includes Kernel, so Kernel gets into every object’s ancestors chain
---------------------------------------------------------------------------------------------------------------------------------------------------------
#令人混淆的self
当前对象-->self:可以理为一个全局变量,在任意时刻只代表一个对象,只有在明确指定方法调用接收者时self才被赋值为该对象.
两种特殊情况:
1.当self的值是main对象时出现class或module定义时self的值会被赋值为定义的class或module对象。
2.在对象A内调用其他对象的方法并返回到A对象后self还是为A对象.
#example:
class C
def initialize(object)
#这里的self是c即C的例
object.methods.grep(/methods$/){
#这里的self仍然是c因为object在调用methods后返回数据,又回到了c的环境中故self此时表示c
C.cla_method
}
end
def self.cla_method
end
end
c = C.new(String)
---------------------------------------------------------------------------------------------------------------------------------------------------------
#动态方法的应用实例:
class Computer
def initialize(computer_id, data_source)
@id = computer_id
@data_source = data_source
data_source.methods.grep(/^get_(.*)_info$/) { Computer.define_component $1 }
end
def self.define_component(name)
define_method(name) {
info = @data_source.send "get_#{name}_info" , @id
price = @data_source.send "get_#{name}_price" , @id
result = "#{name.capitalize}: #{info} ($#{price})"
return "* #{result}" if price >= 100
result
}
end
end
#优点:当data_source增加电脑组件时函数能自动识别并为起定义访问器.
---------------------------------------------------------------------------------------------------------------------------------------------------------
#用method_missing作代理:
class Computer
#to make Computer a blankslate,目的是避免使用method_missing方法代理时与已有方法冲突
#also can directly inherited from BasicObject to be a blankslate.
instance_methods.each do |m|
undef_method m unless m.to_s =~ /^__|method_missing|respond_to?/
end
def initialize(computer_id, data_source)
@id = computer_id
@data_source = data_source
end
def method_missing(name, *args)
super if !@data_source.respond_to?("get_#{name}_info" )
info = @data_source.send("get_#{name}_info" , args[0])
price = @data_source.send("get_#{name}_price" , args[0])
result = "#{name.to_s.capitalize}: #{info} ($#{price})"
return "* #{result}" if price >= 100
result
end
#使respond_to?方法正确显示代理是否能接收某个方法。
def respond_to?(method)
@data_source.respond_to?("get_#{method}_info" ) || super
end
end
#该动态代理缺点在于速度慢,可以通过第一次动态创建方法,下一次直接调用定义的方法进行优化(动态定义方法与动态代理的组合)
#example:
class A
def method_missing(name,*args)
super if !@object.respond_to?(name)
A.class_eval do
define_method name do
puts "create method #{name} successfully!"
end
end
send name
end
end
---------------------------------------------------------------------------------------------------------------------------------------------------------
局部变量的生命周期:进入其范现生成,离开其范围自动消失。
---------------------------------------------------------------------------------------------------------------------------------------------------------
The code in a class or module definition is executed
immediately. Conversely, the code in a method definition is executed
later, when you eventually call the method.
---------------------------------------------------------------------------------------------------------------------------------------------------------
Scope Wrap-Up
#ruby的scope gates:class,module,def
#Flat Scope:(让变量穿越不同的gate)
my_var = "Success"
MyClass = Class.new do
puts "#{my_var} in the class definition!"
define_method :my_method do
puts "#{my_var} in the method!"
end
end
MyClass.new.my_method
#output:
⇒ Success in the class definition!
Success in the method!
#Shared Scope:(在同一个gate内共享变量)
def define_methods
shared = 0
Kernel.send :define_method, :counter do
shared
end
Kernel.send :define_method, :inc do |x|
shared += x
end
end
define_methods
counter # => 0
inc(4)
counter # => 4
#block的变量范围(ruby1.9以后)
def my_method
yield(2)
end
x = 1
y = 1
my_method do |x;y|
#这里的y是声明的块级变量,默认值为nil
puts "inner block x:#{x}, y:#{y}"
end
puts "outer block x:#{x}, y:#{y}"
#inner block x:2, y:
#outer block x:1, y:1
---------------------------------------------------------------------------------------------------------------------------------------------------------
instance_exec( ) is similar to instance_eval( ), but it also allows you to pass arguments to the block.
---------------------------------------------------------------------------------------------------------------------------------------------------------
#Clean Rooms
提供一个干净区域来执行代码块,主要用于减少冲突
#example:
class CleanRoom
def complex_calculation
# ...
end
def do_something
# ...
end
end
clean_room = CleanRoom.new
clean_room.instance_eval do
if complex_calculation > 10
do_something
end
end
---------------------------------------------------------------------------------------------------------------------------------------------------------
package code:
• In a proc, which is basically a block turned object
• In a lambda, which is a slight variation on a proc
• In a method
#notice: proc and lambda are Proc,Proc is a object,but blocks not.
&res变量放在方法参数最后用以接收代码块,此时res就代表proc
yield 只能回调代码块。
----------------------------------------------------------------------------------------------------------------------------------------------------
block,proc,lambda,mehtod object间的差异:
1.method object 几乎与lambda相同只有一点:lambda执行的范围是定义它时的范围(闭包),Method object是在他所在实例的范围内执行。
#method object的例子:
#thod_object = Myclass.new.method :my_method
#method_object.call
2.
---------------------------------------------------------------------------------------------------------------------------------------------------------
keep in mind that a class is just a souped-up module, so anything you
learn about classes also applies to modules.
---------------------------------------------------------------------------------------------------------------------------------------------------------
#***********Import**********
#instance_eval() changes self, and class_eval() changes both self and the current class
#关于instance_eval() 与 class_eval()
1.class_eval顾名思义就是在类环境中执行代码,相当于reopen the class(注:module_eval是其别名,他们只能对class或module使用)
instance_eval就是在对象中执行代码(注意classes也是对象)
2.若对象使用instance_eval定义方法,那么方法是该对象的singleton_method(若该对象是类那么定义的方法为class_method)
若类使用class_eval定义方法,那么方法是类的instance_method
---------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------
#关于instance_variable和class_instancece_variable
1.实例变量被存储在实例对象里,只在该对象内共享,不能被该对象的实例或子类使用
2.类也是对象,所以类实例变量只能在类对象内共享
#example:
class MyClass
@my_var = 1 #class_instance_variable
def self.read; @my_var; end
def write; @my_var = 2; end #instance_variable
def read; @my_var; end
end
obj = MyClass.new
obj.write
obj.read # => 2
MyClass.read # => 1
---------------------------------------------------------------------------------------------------------------------------------------------------------
#@@v被定义在main对象的环境中,main是Object类的实例,然而MyClass是Ojcect的子类
#所以MyClass继承了class_variable @vv,故最后结果是2
@@v = 1
class MyClass
@@v = 2
end
@@v # => 2
---------------------------------------------------------------------------------------------------------------------------------------------------------
Class#new( ) also accepts an argument (the superclass of thenew class)
and a block that is evaluated in the context of the newborn class:
#example:
c = Class.new(Array) do
def my_method
'Hello!'
end
end
---------------------------------------------------------------------------------------------------------------------------------------------------------
类方法就是类的singleton方法
#def obj.a_singleton_method; end
#def MyClass.another_class_method; end
---------------------------------------------------------------------------------------------------------------------------------------------------------
#当一个类在被其他类调用时怎么进行重构?
class Book
def title # ...
def subtitle # ...
def lend_to(user)
puts "Lending to #{user}"
# ...
def self.deprecate(old_method, new_method)
define_method(old_method) do |*args, &block|
warn "Warning: #{old_method}() is deprecated. Use #{new_method}()."
send(new_method, *args, &block)
end
end
deprecate :GetTitle, :title
deprecate :LEND_TO_USER, :lend_to
deprecate :title2, :subtitle
end
#b = Book.new
#b.LEND_TO_USER("Bill" )
#⇒ Warning: LEND_TO_USER() is deprecated. Use lend_to().
# Lending to Bill
---------------------------------------------------------------------------------------------------------------------------------------------------------
#eigenclass只有一个实例且不能被继承,对象的singleton方法就放在eigenclass里面。
#singleton method
def obj.my_singleton_method; end
eigenclass.instance_methods.grep(/my_/) # => ["my_singleton_method"]
#class mehtod
class MyClass
def self.my_method; end
end
def MyClass.my_other_method; end
class MyClass
class << self
def my_method; end
end
end
---------------------------------------------------------------------------------------------------------------------------------------------------------
#****************Important***************************
#通过include module定义类方法
#one way:
module MyModule
def my_method; 'hello' ; end
end
class MyClass
class << self
include MyModule
end
end
MyClass.my_method # => "hello"
#second way:
Object#extend( ) is simply a shortcut that includes a module in the
receiver’s eigenclass.
#example:
class MyClass
extend Mymodule
end
MyClass.my_method # => "hello"
#通过include module 引入类方法。
module MyMixin
def self.included(base)
base.extend(self) #将该module里的所有方法变为类方法(base-->代表引用该模块的类,self是module:MyMixin).
end
def x
"x()"
end
end
---------------------------------------------------------------------------------------------------------------------------------------------------------
# alias是keyword,不是方法.
# Module#alias_method(),是一个方法与alias效果一样.
class String
alias :real_length :length
def length
real_length > 5 ? 'long' : 'short'
end
end
"War and Peace".length # => "long"
"War and Peace".real_length # => 13
#an example of gem
module Kernel
alias gem_original_require require
def require(path) # :doc:
gem_original_require path
rescue LoadError => load_error
if load_error.message =~ /#{Regexp.escape path}\z/ and
spec = Gem.searcher.find(path) then
Gem.activate(spec.name, "= #{spec.version}" )
gem_original_require path
else
raise load_error
end
end
end
#写一个Around Alias的步骤:
1.alias一个方法
2.重定义它
3.从新方法里面访问老方法
---------------------------------------------------------------------------------------------------------------------------------------------------------
#关于 eval()
Ruby 不会报告代字符串形式的代码里面的错误,直到那段字符串被执行。
---------------------------------------------------------------------------------------------------------------------------------------------------------
#一个钩子方法的应用例子:
module M; end
class C
def self.include(*modules)
puts "Called: C.include(#{modules})"
super #执行原始include方法
end
include M
end
⇒Called: C.include(M)
---------------------------------------------------------------------------------------------------------------------------------------------------------
#Think in Modules
ruby module 就是一个用于定于方法的地方
ruby class 就是module的集合(a souped-up module)
---------------------------------------------------------------------------------------------------------------------------------------------------------
Fiber 主要特性保留状态,具备连续性(断点续传),调用者与Fiber能进行值传递。
所有的迭代器都是促发了循环请求yield来执行代码块