instance_eval方法
这个BasicObject#instance_eval有点类似JS中的bind方法,不同的时,bind是将this传入到对象中,而instance_eval则是将代码块(上下文探针Context Probe)传入到指定的对象中,一个是传对象,一个是传执行体。通过这种方式就可以在instance_eval中的代码块里访问到调用者对象中的变量。
示例代码
class MyClass def initialize @v = 1 end end obj = MyClass.new obj.instance_eval do self #=> #<MyClass:0x33333 @v=1> @v #=> 1 end v = 2 obj.instance_eval { @v = v } obj.instance_eval { @v } # => 2
此外,instance_eval方法还有一个双胞胎兄弟:instance_exec方法。相比前者后者更加灵活,允许对代码块传入参数。
示例代码
class C def initialize @x = 1 end end class D def twisted_method @y = 2 #C.new.instance_eval { “@x: #{@x}, @y>: #{y}” } C.new.instance_exec(@y) { |y| “@x: #{@x}, @y: #{y}” } end end #D.new.twisted_method # => “@x: 1, @y: ” D.new.twisted_method # => “@x: 1, @y: 2”
因为调用instance_eval后,将调用者作为了当前的self,所以作用域更换到了class C中,之前的作用域就不生效了。这时如果还想访问到之前@y变量,就需要通过参数打包上@y一起随instance_eval转义,但因为instance_eval不能携带参数,所以使用其同胞兄弟instance_exec方法。
instance_eval 与 class_eval 的区别
###instance_eval
首先从名字可以得到的信息是,instance_eval的调用者receiver必须是一个实例instance,而在instance_eval block的内部,self即为receiver实例本身。
obj_instance.instance_eval do self # => obj_instance # current class => obj_instance's singleton class end <!--more-->
根据这个定义,如果在一个实例上调用了instance_eval,就可以在其中定义该实例的单态函数 singleton_method
class A end a = A.new a.instance_eval do self # => a # current class => a's singleton class def method1 puts 'this is a singleton method of instance a' end end a.method1 #=> this is a singleton method of instance a b = A.new b.method1 #=>NoMethodError: undefined method `method1' for #<A:0x10043ff70>
同样,因为类class本身也是Class类的一个实例,instance_eval也可以用在类上,这个时候就可以在其中定义该类的singleton_method,即为该类的类函数。
换句话说,可以用instance_eval来定义类函数class method,这比较容易混淆,需要搞清楚。
class A end A.instance_eval do self # => A # current class => A's singleton class def method1 puts 'this is a singleton method of class A' end end A.method1 #=> this is a singleton method of class A class_eval
###class_eval
再来看class_eval,首先从名字可以得到的信息是,class_eval的调用者receiver必须是一个类,而在class_eval block的内部,self即为receiver类本身。
class A end A.class_eval do self # => A # current class => A end
根据这个定义,如果在一个类上调用了class_eval,就可以在其中定义该类的实例函数 instance_method
class A end a = A.new a.method1 #=> NoMethodError: undefined method `method1' for #<A:0x10043ff70> A.class_eval do self # => A # current class => A def method1 puts 'this is a instance method of class A' end end a.method1 #=> this is a instance method of class A
换句话说,可以用class_eval来定义实例函数instance method,这也比较容易混淆,需要搞清楚。
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
更新日志
- 雨林唱片《赏》新曲+精选集SACD版[ISO][2.3G]
- 罗大佑与OK男女合唱团.1995-再会吧!素兰【音乐工厂】【WAV+CUE】
- 草蜢.1993-宝贝对不起(国)【宝丽金】【WAV+CUE】
- 杨培安.2009-抒·情(EP)【擎天娱乐】【WAV+CUE】
- 周慧敏《EndlessDream》[WAV+CUE]
- 彭芳《纯色角3》2007[WAV+CUE]
- 江志丰2008-今生为你[豪记][WAV+CUE]
- 罗大佑1994《恋曲2000》音乐工厂[WAV+CUE][1G]
- 群星《一首歌一个故事》赵英俊某些作品重唱企划[FLAC分轨][1G]
- 群星《网易云英文歌曲播放量TOP100》[MP3][1G]
- 方大同.2024-梦想家TheDreamer【赋音乐】【FLAC分轨】
- 李慧珍.2007-爱死了【华谊兄弟】【WAV+CUE】
- 王大文.2019-国际太空站【环球】【FLAC分轨】
- 群星《2022超好听的十倍音质网络歌曲(163)》U盘音乐[WAV分轨][1.1G]
- 童丽《啼笑姻缘》头版限量编号24K金碟[低速原抓WAV+CUE][1.1G]