ruby 中所有的东西都是对象,包括一些基础的Object,Class, Module。
可以把ruby中的类和实例都统一的理解为实例。像Class这样的特殊的实例,因为有new方法,所以可以产
生新的实例。
既然所有的东西都是实例,那对于新实例的产生和新类的产生是如何工作的?
instance中的方法和变量分为2部分,一部分叫object 方法,一部分叫instance 方法, 变量也一样。
所以,当用new产生新的实例的时候,mother instance 中的instance methods 被用链接的方式copy到child instance 中, 作为child instance 的 object 方法存在. 也就是说,对于每一个instance, 其中>的object method是给自己用的,instance method 是给用new生出来的孩子用的。
当用继承的方式产生一个新的instance的时候,mother instance 的所有method 都被链接copy到新的instance中去。
所以,以这个理解为基础,
Object.instance_eval 添加的是object method
Object.extend_object 添加的是object method
Module.class_eval 添加的是instance method
Module.define_method 添加的是instance method
所以 用class 关键字声明一个类的时候,实际上就是产生一个类的实例,和用Class.new的效果是一样的。
都说自己定义的Module没有new方法,那是因为自己在定义module的时候没有添加new方法,对于ruby内置的Module, 是有new方法的,所以在生成一个新的module的时候,也可以用Module.new的方式。
Object,Module,Class的mother instance 都是Class, 然而Class又继承于Mudle,Module继承于Object, 如果是静态语言的话,这样的循环会有编译的问题,因为,哪一个都不能被先编译。
但是对于动态语言,我可以先执行Class的定义,然后执行Object和Module的继承,最后再从新扩展Class,让它继承Module。 说白了,这些操作就是对object内部的函数表和变量表进行操作,所以没有问题。
最后,贴点代码:
MyModule = Module.new
MyModule.class_eval(%q{
def hello()
puts "hello"
end
def self.cry()
puts "self.cry"
end
})
MyModule.cry
MyModule.instance_eval %Q{
def cry()
puts "self.cry by instance_eval"
end
}
MyModule.cry
MyModule.send(:define_method, :shout) do |words|
puts "MyModule is shouting!"
end
puts MyModule.methods.size
puts MyModule.instance_methods.size
puts MyModule.singleton_methods.size
puts "=" * 30
MyClass = Class.new
MyClass.send(:include, MyModule)
MyClass.new.hello
MyClass.new.shout "abc"
MyClass.class_eval %Q{
def self.cry()
puts "self.cry by MyClass.class_eval"
end
}
MyClass.cry
# to prove instance methods is copied from mother object to child object.
my_class = MyClass.new
puts MyClass.instance_methods.size
MyClass.class_eval %Q{
def cry()
puts "self.cry by MyClass.class_eval"
end
}
puts my_class.methods.size
puts MyClass.instance_methods.size
puts MyClass.methods.size
运行结果:
RubyMate r8136 running Ruby r1.8.6 (/usr/local/bin/ruby)
>>> my_module.rb
self.cry
self.cry by instance_eval
74
2
1
==============================
hello
MyModule is shouting!
self.cry by MyClass.class_eval
44
45
45
77
可以把ruby中的类和实例都统一的理解为实例。像Class这样的特殊的实例,因为有new方法,所以可以产
生新的实例。
既然所有的东西都是实例,那对于新实例的产生和新类的产生是如何工作的?
instance中的方法和变量分为2部分,一部分叫object 方法,一部分叫instance 方法, 变量也一样。
所以,当用new产生新的实例的时候,mother instance 中的instance methods 被用链接的方式copy到child instance 中, 作为child instance 的 object 方法存在. 也就是说,对于每一个instance, 其中>的object method是给自己用的,instance method 是给用new生出来的孩子用的。
当用继承的方式产生一个新的instance的时候,mother instance 的所有method 都被链接copy到新的instance中去。
所以,以这个理解为基础,
Object.instance_eval 添加的是object method
Object.extend_object 添加的是object method
Module.class_eval 添加的是instance method
Module.define_method 添加的是instance method
所以 用class 关键字声明一个类的时候,实际上就是产生一个类的实例,和用Class.new的效果是一样的。
都说自己定义的Module没有new方法,那是因为自己在定义module的时候没有添加new方法,对于ruby内置的Module, 是有new方法的,所以在生成一个新的module的时候,也可以用Module.new的方式。
Object,Module,Class的mother instance 都是Class, 然而Class又继承于Mudle,Module继承于Object, 如果是静态语言的话,这样的循环会有编译的问题,因为,哪一个都不能被先编译。
但是对于动态语言,我可以先执行Class的定义,然后执行Object和Module的继承,最后再从新扩展Class,让它继承Module。 说白了,这些操作就是对object内部的函数表和变量表进行操作,所以没有问题。
最后,贴点代码:
MyModule = Module.new
MyModule.class_eval(%q{
def hello()
puts "hello"
end
def self.cry()
puts "self.cry"
end
})
MyModule.cry
MyModule.instance_eval %Q{
def cry()
puts "self.cry by instance_eval"
end
}
MyModule.cry
MyModule.send(:define_method, :shout) do |words|
puts "MyModule is shouting!"
end
puts MyModule.methods.size
puts MyModule.instance_methods.size
puts MyModule.singleton_methods.size
puts "=" * 30
MyClass = Class.new
MyClass.send(:include, MyModule)
MyClass.new.hello
MyClass.new.shout "abc"
MyClass.class_eval %Q{
def self.cry()
puts "self.cry by MyClass.class_eval"
end
}
MyClass.cry
# to prove instance methods is copied from mother object to child object.
my_class = MyClass.new
puts MyClass.instance_methods.size
MyClass.class_eval %Q{
def cry()
puts "self.cry by MyClass.class_eval"
end
}
puts my_class.methods.size
puts MyClass.instance_methods.size
puts MyClass.methods.size
运行结果:
RubyMate r8136 running Ruby r1.8.6 (/usr/local/bin/ruby)
>>> my_module.rb
self.cry
self.cry by instance_eval
74
2
1
==============================
hello
MyModule is shouting!
self.cry by MyClass.class_eval
44
45
45
77