`
googya
  • 浏览: 143310 次
  • 性别: Icon_minigender_1
  • 来自: 汉川
社区版块
存档分类
最新评论

令人迷惑的class_eval和instance_eval

阅读更多

按照yugui 大姐的说法,class_eval和instance_eval有如下的区别:



class&instance_eval              self                            default definee
class_eval                          the receiver                   the receiver
instance_eval                   the receiver                     eigenclass of the receiver




上面就是class_eval与instance_eval的区别了,一般情况下这个没有问题(个人感觉)。但还是会有令迷惑的地方。
下面的例子说明了,在下面情况下,class_eval和instance_eval的作用没有区别。

class A
end
class Object
	def eigenclass
		class << self;self;end
	end
end
A.class_eval do
p self
	def hehe
		"hehe"
	end
	define_method(:xixi) do
		"xixi"
	end
end

A.instance_eval do
p self
	def haha;"haha";p self ;end
end

A.instance_eval do
p self
	define_method(:hihi) do
		"hihi"
		p self.to_s
	end
end
 
 A.haha
 A.new.hihi
 p A.instance_methods
 p  "*"*120
 p A.eigenclass.instance_methods

    定义的hihi和xixi都是A是实例方法。


 jayfield  
说到:

define_method always defines an instance method on the target (Foo in our example). This makes sense because define_method is being call on the implicit self, which evaluates to the receiver (Foo) in our example."[/

 


jayfield的说法应该是有问题的,但不这样理解,上面的例子怎么又说得通呢?



PS:可能是我表述不清还是怎么的,基本上没有人对此关注。实际上我想说的就是:

A.instance_eval do 
p self 
def haha;"haha";p self ;end 
end 

A.instance_eval do 
p self 
define_method(:hihi) do 
"hihi" 
p self.to_s 
end 
end 

 



   同样是用instance_eval,为什么有这么大的不同。

A.new.hihi 
A.haha 

 

事实上,

A.instance_eval do
p self
define_method(:hihi) do
"hihi"
p self.to_s
end
end

 

 

与 class A

 

  define_method(:hihi) do

     "hihi"

 

end

end

的效果是一样的,define_method是个私有方法,能调用(隐式)它的只能是类对象而非一般的对象。

 

 

 

 


  在一个网站 上看到了这个:

 

 

现在可以比较直观的理解这二者的不同了

 

  • 大小: 29.9 KB
分享到:
评论
16 楼 googya 2011-10-04  
googya 写道
axgle 写道
define_method always defines an instance method on the target

A.instance_eval do 
p self 
     define_method(:hihi) do 
         "hihi" 
         p self.to_s 
    end 
end 
axgle说的是一般情况。上面这个例子就是定义了一个实例方法,如何解释?



给类对象创建一个实例方法。。。。。那个target就是 A,不管A用instance_eval 或者是 class_eval都是一样的
15 楼 consy 2010-12-29  
<p><span style="font-size: x-small;">ruby中虽说类也是对象,但类对象跟普通对象是不同的,其中方法(im_tbl)是存储在类中的,并且类还有个super指针来表示继承关系,这是普通对象所不具有的特征。所以可以认为类具有类跟普通对象的双重身份(个人说法...)。instance_eval与class_eval内的self都是方法的接受者,也就是不管是A.instance_eval还是A.class_eval后面所结的代码块的隐含self对象都是A。而define_method是个私有方法。既然是方法,那么在A.instance_eval和A.class_eval中其调用效果都是一样,因为define_method的接受者都是A这个类对象(self),所以在哪调用都是一样的,那么define_method方法所定义的方法就成了了A这个类的实例方法了。而def是个关键字,这个关键字是给类定义方法(方法是存储在类中的)。正如lllyq所说:</span></p>
<p><span style="font-size: x-small;">顾名思义<br>instance_eval 就是实例级别的eval<br>class_eval 就是类级别的eval<br><br>A.instance_eval =&gt; open A's singleton instance<br>A.new.instance_eval =&gt; open A.new<br>A.class_eval =&gt; open A<br>class_eval很明显是把接受者当类来看待,所以这个方法只能由类对象来调用,A.class_eval中用def关键字定义方法自然是给A这个类定义方法,应该是</span><span style="font-size: x-small;">hf_cn81所说的ruby_class</span><span style="font-size: x-small;">,这跟类的定义差不多。而A.instance_eval则明显的把A当成一个对象,方法不是存储在对象中的,既然此处不把A当成类,那def定义的方法自然不能是给A定义的(因为A是对象而非类)。所以A.instance_eval中使用def关键字定义的方法就定义到了A这个对象的单例类中了,也就成了A的类方法。</span></p>
<p><span style="font-size: x-small;">我想大概是这样的,不知对也不对大家讨论...</span></p>
<p><span style="font-size: x-small;"><br></span></p>
14 楼 lllyq 2010-09-27  
<div class="quote_title">hf_cn81 写道</div>
<div class="quote_div">
<p>instance_eval里的self就是receiver,这和class_eval没有区别,所以</p>
<p>A.instance_eval do</p>
<p><span style="white-space: pre;"> </span>puts self</p>
<p>end</p>
<p> </p>
<p>A.class_eval do</p>
<p><span style="white-space: pre;"> </span>puts self</p>
<p>end</p>
<p>打印的结果一样,但是instance_eval改变了“ruby_class”到A的meta class,而class_eval则将“ruby_class"改成A。</p>
<p>def定义的方法是做为”ruby_class“的实例方法,而define_method定义的方法是作为self的实例方法。</p>
<p> </p>
</div>
<p>回头看看还是hf_cn81说的比较到位</p>
13 楼 googya 2010-09-27  
从这么多个给我投新手帖的情况来看,我觉得可以反映出2个问题:

1、很多人很轻视这个问题。yehuda这个Ruby顶尖高手都曾经在这个问题上犯过错误,     可 见这个问题确实有点迷惑性,因而我觉得有讨论它的价值。从回帖的情况来看,并不是所有人都认清了这个问题的本质。

2、不宽容。那些没有留下只言片语却投了新手帖的人,我不知道他们是什么心态。难道他们都是nb的不行的人物?也许吧,那请你回答这个问题啊,或者可以给点提示、努力的方向都可以啊。

当然对我而言,确实是Ruby新手。但是这个问题却不是那么的simple,也不是那么的stupid。
12 楼 googya 2010-09-27  
lllyq 写道
顾名思义
instance_eval 就是实例级别的eval
class_eval 就是类级别的eval

A.instance_eval => open A's singleton instance
A.new.instance_eval => open A.new
A.class_eval => open A


嗯,你说的不错,确实,按照字面上的理解确实如此!
但是关键的问题在于:

A.instance_eval do

    define_method(:hihi) do  
        "hihi"  
        p self.to_s  
   end  
end


这二者的组合产生的效果是什么样的。
A.instance_eval 打开了通往A的eigenclass 的门,在那个门内的方法,按道理来说,仅仅是为A定义的,也就说应该是A单独享有的方法(其实例都不能享有)。但是实际的情况并非如此!hihi这个方法是为A的实例定义的,这也是我疑惑的地方所在。
   
    不过我想我已经弄清楚了具体的原因!





   





11 楼 ye_jian_hui 2010-09-25  
lllyq 写道
顾名思义
instance_eval 就是实例级别的eval
class_eval 就是类级别的eval

A.instance_eval => open A's singleton instance
A.new.instance_eval => open A.new
A.class_eval => open A


正解!
10 楼 lllyq 2010-09-24  
顾名思义
instance_eval 就是实例级别的eval
class_eval 就是类级别的eval

A.instance_eval => open A's singleton instance
A.new.instance_eval => open A.new
A.class_eval => open A
9 楼 tjcjc 2010-08-31  
target就是self吧
A.instance_eval{puts self}
A.class_eval{puts self}
出来的结果都是A
所以在这两个里面的define_method都是给A定义一个实例方法
instance_eval与class_eval只是给define_method提供了一个self环境
8 楼 googya 2010-08-31  
axgle 写道
define_method always defines an instance method on the target

关键问题是:这个target是指的什么
7 楼 xds2000 2010-06-06  
我也困惑过。我也来谈谈。
instance_eval,名字上就有instance,就是实例。
什么是实例?a = A.new ,这个a就是实例。
我再自问一句,a实例是什么?
因为在ruby世界里什么都是对象,那个a这个对象其实就是A的单例。
所以你可以这样
def a.method1
   puts 'this is singleton method'
end

a.method1

所以也会有
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>

我在想,Ruby是一个语言的大杂烩,不会像Python那样优雅,所以它一定是遵循一种简单的语义。所以我们不能像别其它语言那样,把高度看太高,其实想过来很简单。

coding in fun!
============
class_eval是为Class定义函数。
我知道只要在Class里定义的函数,它的实例就相应得到了这些函数。
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


参考:
http://note.jiaeil.com/2010/05/16/digging-ruby-instance_eval-and-class_eval/


6 楼 googya 2010-06-06  
<div class="quote_title">hf_cn81 写道</div>
<div class="quote_div">
<p>instance_eval里的self就是receiver,这和class_eval没有区别,所以</p>
<p>A.instance_eval do</p>
<p><span style="white-space: pre;"> </span>puts self</p>
<p>end</p>
<p> </p>
<p>A.class_eval do</p>
<p><span style="white-space: pre;"> </span>puts self</p>
<p>end</p>
<p>打印的结果一样,但是instance_eval改变了“ruby_class”到A的meta class,而class_eval则将“ruby_class"改成A。</p>
<p>def定义的方法是做为”ruby_class“的实例方法,而define_method定义的方法是作为self的实例方法。</p>
<p> </p>
</div>
<p> </p>
<p> </p>
<p>照你的意思,instance_eval中应该有2个不同的self.一个是可以打印出来的的那个,一个就是更改后的ruby_class。对吗?</p>
5 楼 hf_cn81 2010-06-05  
<p>instance_eval里的self就是receiver,这和class_eval没有区别,所以</p>
<p>A.instance_eval do</p>
<p><span style="white-space: pre;"> </span>puts self</p>
<p>end</p>
<p> </p>
<p>A.class_eval do</p>
<p><span style="white-space: pre;"> </span>puts self</p>
<p>end</p>
<p>打印的结果一样,但是instance_eval改变了“ruby_class”到A的meta class,而class_eval则将“ruby_class"改成A。</p>
<p>def定义的方法是做为”ruby_class“的实例方法,而define_method定义的方法是作为self的实例方法。</p>
<p> </p>
4 楼 googya 2010-06-04  
<div class="quote_title">hf_cn81 写道</div><div class="quote_div"><p><span style=""><span style=""><ol class="dp-rb" style="font-size: 1em; line-height: 1.4em; margin-top: 0px; margin-right: 0px; margin-bottom: 1px; margin-left: 0px; padding-top: 2px; padding-right: 0px; padding-bottom: 2px; padding-left: 0px; background-color: #ffffff; color: #2b91af; border: 1px solid #d1d7dc;">
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;"><span style="color: black;">A.instance_eval </span><span class="keyword" style="color: #7f0055; font-weight: bold;">do</span><span style="color: black;">  </span></span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;">p <span class="keyword" style="color: #7f0055; font-weight: bold;">self</span><span style="color: black;">  </span></span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;">    <span class="keyword" style="color: #7f0055; font-weight: bold;">def</span><span style="color: black;"> haha;</span><span class="string" style="color: blue;">"haha"</span><span style="color: black;">;p </span><span class="keyword" style="color: #7f0055; font-weight: bold;">self</span><span style="color: black;"> ;</span><span class="keyword" style="color: #7f0055; font-weight: bold;">end</span><span style="color: black;">  </span></span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;"><span class="keyword" style="color: #7f0055; font-weight: bold;">end</span><span style="color: black;">  </span></span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;">  </span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;">A.instance_eval <span class="keyword" style="color: #7f0055; font-weight: bold;">do</span><span style="color: black;">  </span></span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;">p <span class="keyword" style="color: #7f0055; font-weight: bold;">self</span><span style="color: black;">  </span></span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;">    <span class="keyword" style="color: #7f0055; font-weight: bold;">define_method</span><span style="color: black;">(</span><span class="symbol" style="color: #aa7700;">:hihi</span><span style="color: black;">) </span><span class="keyword" style="color: #7f0055; font-weight: bold;">do</span><span style="color: black;">  </span></span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;">        <span class="string" style="color: blue;">"hihi"</span><span style="color: black;">  </span></span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;">        p <span class="keyword" style="color: #7f0055; font-weight: bold;">self</span><span style="color: black;">.to_s  </span></span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;">    <span class="keyword" style="color: #7f0055; font-weight: bold;">end</span><span style="color: black;">  </span></span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;"><span class="keyword" style="color: #7f0055; font-weight: bold;">end</span><span style="color: black;">  </span></span></li>
</ol></span></span></p>
<p>def 是ruby的关键字,他会定义方法到当前的ruby_class(一个隐藏的变量), instance_eval会改变ruby_class,使之成为receiver(A)的meta class(而class_eval则将其变为receiver),所以def定义的方法,就是A的方法(类方法)或者说是A的meta class的实例方法, define_method是ruby中Module的方法,用于定义self的实例方法,instance_eval不会改变self,所以hihi是A的实例方法。</p></div><br/>instance_eval 肯定会改变self,无论是用def或者define_method这点可以保证的。
3 楼 hf_cn81 2010-06-04  
<p><span style=""><span style=""><ol class="dp-rb" style="font-size: 1em; line-height: 1.4em; margin-top: 0px; margin-right: 0px; margin-bottom: 1px; margin-left: 0px; padding-top: 2px; padding-right: 0px; padding-bottom: 2px; padding-left: 0px; background-color: #ffffff; color: #2b91af; border: 1px solid #d1d7dc;">
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;"><span style="color: black;">A.instance_eval </span><span class="keyword" style="color: #7f0055; font-weight: bold;">do</span><span style="color: black;">  </span></span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;">p <span class="keyword" style="color: #7f0055; font-weight: bold;">self</span><span style="color: black;">  </span></span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;">    <span class="keyword" style="color: #7f0055; font-weight: bold;">def</span><span style="color: black;"> haha;</span><span class="string" style="color: blue;">"haha"</span><span style="color: black;">;p </span><span class="keyword" style="color: #7f0055; font-weight: bold;">self</span><span style="color: black;"> ;</span><span class="keyword" style="color: #7f0055; font-weight: bold;">end</span><span style="color: black;">  </span></span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;"><span class="keyword" style="color: #7f0055; font-weight: bold;">end</span><span style="color: black;">  </span></span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;">  </span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;">A.instance_eval <span class="keyword" style="color: #7f0055; font-weight: bold;">do</span><span style="color: black;">  </span></span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;">p <span class="keyword" style="color: #7f0055; font-weight: bold;">self</span><span style="color: black;">  </span></span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;">    <span class="keyword" style="color: #7f0055; font-weight: bold;">define_method</span><span style="color: black;">(</span><span class="symbol" style="color: #aa7700;">:hihi</span><span style="color: black;">) </span><span class="keyword" style="color: #7f0055; font-weight: bold;">do</span><span style="color: black;">  </span></span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;">        <span class="string" style="color: blue;">"hihi"</span><span style="color: black;">  </span></span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;">        p <span class="keyword" style="color: #7f0055; font-weight: bold;">self</span><span style="color: black;">.to_s  </span></span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;">    <span class="keyword" style="color: #7f0055; font-weight: bold;">end</span><span style="color: black;">  </span></span></li>
<li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px;"><span style="color: black;"><span class="keyword" style="color: #7f0055; font-weight: bold;">end</span><span style="color: black;">  </span></span></li>
</ol></span></span></p>
<p>def 是ruby的关键字,他会定义方法到当前的ruby_class(一个隐藏的变量), instance_eval会改变ruby_class,使之成为receiver(A)的meta class(而class_eval则将其变为receiver),所以def定义的方法,就是A的方法(类方法)或者说是A的meta class的实例方法, define_method是ruby中Module的方法,用于定义self的实例方法,instance_eval不会改变self,所以hihi是A的实例方法。</p>
2 楼 googya 2010-06-01  
axgle 写道
define_method always defines an instance method on the target

A.instance_eval do 
p self 
     define_method(:hihi) do 
         "hihi" 
         p self.to_s 
    end 
end 
axgle说的是一般情况。上面这个例子就是定义了一个实例方法,如何解释?
1 楼 axgle 2010-05-31  
define_method always defines an instance method on the target

相关推荐

    Ruby Meta Programming: define_method or class_eval

    `define_method`和`class_eval`是Ruby元编程中的两个关键方法,它们被广泛用于动态地添加方法到类或者模块中。这篇文章将深入探讨这两个方法的用法和区别。 `define_method`方法允许我们传递一个符号和一个代码块来...

    详解Ruby中的instance_eval方法及其与class_eval的对比

    **instance_eval** 和 **class_eval** 虽然都是用来执行代码块的方法,但它们之间存在一些重要的区别: ##### 2.1 instance_eval - **调用者**: 必须是一个实例。 - **内部的self**: 在 `instance_eval` 块内部,`...

    Core-Ruby-1:2014 年 10 月开始的 Core Ruby 课程的报告

    核心-Ruby-1 类的存储库。... 不要作恶:class_eval 和 instance_eval。 常量、实例变量 API。 6 自由修补。 改进。 关键字参数。 在 2.1 中风靡一时。 7 线程或:我如何学会停止担心并学会热爱 GI

    java动态特性eval

    在模拟`eval()`功能时,我们可能需要使用`Class.forName()`加载类,`Method.invoke()`执行方法,或者`Constructor.newInstance()`创建对象。通过这些反射方法,我们可以解析字符串并执行相应的Java代码。 2. **Java...

    metaprogramming_introduction:一篇以源代码形式介绍Ruby元编程基础知识的文章-Form source code

    通过`eval`, `send`, `instance_eval`, `class_eval`, 动态方法定义,以及`Proc`和`Lambda`等工具,开发者能够创建出更具适应性和可扩展性的代码。在实际项目中,合理利用元编程可以提高代码的效率和可维护性,但...

    ruby metaprogramming examples

    6. 实例化时方法注入(Instance_eval & Class_eval):这些方法可以改变当前对象的上下文,允许你访问或修改实例变量和方法。`instance_eval`允许你评估一段代码并将其作用域限定在当前实例上,而`class_eval`则用于...

    ruby中文文档.chm

    8. **元编程**:探索Ruby的send方法、class_eval、instance_eval等元编程技巧。 9. **Gem和包管理**:了解Ruby的包管理系统RubyGems,以及如何安装和使用第三方库。 10. **Ruby on Rails**:如果文档包含相关内容,...

    Programming Ruby 2nd Edition

    书中会讲解send、class_eval、instance_eval等元编程工具的使用。 6. **标准库**:Ruby的标准库提供了大量实用的模块和类,如File、Net、Time等,可以帮助开发者快速实现各种功能。 7. **Ruby on Rails**:虽然...

    Ruby元编程第二版中文

    `class_eval`和`module_eval`允许在类或模块上下文中执行字符串或块作为代码。 3. **对象的反射**:`Object#methods`、`Class#methods`等方法返回对象或类可调用的方法列表。`instance_variable_get`和`instance_...

    ruby官方chm文档

    理解如何使用`eval`、`class_eval`和`instance_eval`,以及如何利用`send`和`method_missing`进行消息传递,是提升Ruby编程技巧的关键。 《ruby23.chm》文档可能是整个Ruby语言的综合指南,可能包含前面几个文档的...

    ruby_1_9_3_core_rdocs.gz

    8. **元编程**:Ruby的元编程能力是其一大特色,通过`class_eval`、`instance_eval`和`define_method`等方法,可以在运行时动态修改类和对象的行为。 9. **线程与并发**:Ruby 1.9.3引入了全局解释器锁(GIL),...

    Ruby-Way.rar_About Language

    例如,你可以使用`define_method`动态定义方法,或者使用`class_eval`或`instance_eval`在运行时改变类的行为。这种特性极大地增强了代码的灵活性和可扩展性。 《Ruby Way》一书还会详细介绍Ruby的Gem包管理器,Gem...

    [Ruby完全自学手册].邓蔚.扫描版

    例如,读者将学习到如何使用 `class_eval` 和 `instance_eval` 动态定义类和方法,以及 `send` 方法的用法。 此外,本书还会涵盖Ruby的错误处理和异常处理机制,以及测试驱动开发(TDD)和集成测试的相关知识,帮助...

    ruby设计模式的代码有好多

    Ruby的元编程能力,如`class_eval`、`instance_eval`和`define_method`等方法,使得动态修改类和对象的行为变得容易,这在实现某些设计模式时特别有用。例如,元编程可以用来在运行时添加方法,实现动态代理或者创建...

    脚本编程之: ruby_bcyy_jb51.net

    6. **元编程**:Ruby的元编程特性,如`class_eval`、`instance_eval`、`method_missing`等,以及如何利用它们来增强代码的动态性。 7. **测试驱动开发(TDD)**:Ruby社区非常注重TDD,因此可能包含关于Rspec或Test::...

    ruby 帮助文档资料

    通过`eval`函数、`instance_eval`、`class_eval`等方法,开发者可以在运行时动态修改或创建代码。这使得Ruby在构建高度自定义和灵活的系统时具有极大的优势。 Ruby的工具生态也非常丰富,其中最著名的是Ruby on ...

    一些高质量的学习Ruby的资源清单.zip

    了解 `class_eval`、`instance_eval`、`define_method` 等方法可以帮助你更深入地掌握这一特性。 6. **测试驱动开发(TDD)**:Ruby 社区强调 TDD,因此熟悉 RSpec 或 MiniTest 这样的测试框架是必要的。学会编写...

    ruby-2.5.1

    `eval`函数可以执行字符串作为Ruby代码,`send`方法可以动态调用对象的方法,而`instance_eval`和`class_eval`则可以在特定上下文中执行代码,极大地增加了代码的灵活性。 在Ruby 2.5.1中,标准库也得到了增强,...

    ruby入门教程

    例如,你可以使用`define_method`动态定义方法,或者使用`class_eval`或`instance_eval`来执行字符串中的代码,这在编写灵活的框架或库时非常有用。 此外,Ruby的标准库非常丰富,提供了大量实用的模块和函数。例如...

Global site tag (gtag.js) - Google Analytics