CWYAlpha

Just another WordPress.com site

Thought this was cool: 吐槽一下Ruby里面的奇技淫巧

leave a comment »


Ruby的元编程是很强大,用起来也方便。但是一般来说,太方便太灵活的东西有时候也不一定全是好事——这意味着坑会比较多,一不小心就跳进去了。这里吐槽一下一些Gem里面用到的技巧。

module MyModule
  def self.included(base)
    base.extend Extend
  end
  def dance; puts "dancing"; end
  module Extend
    def sing; puts "lalala"; end
  end
end

class MyClass
  include MyModule
end

刚开始我真搞不明白为什么要这样写。可以直接在class里面extend一个module,为什么要把included改掉?其实作者的本意是只extend一些特定的方法,而不是所有方法。那么,为什么不像下面这样写?

module MyModule
  def self.extended(base)
    base.extend Extend
  end
  def dance; puts "dancing"; end
  module Extend
    def sing; puts "lalala"; end
  end
end

class MyClass
  include MyModule
end

开始我以为第一种写法真是多余,后面发现还真不是。按照第二种写法,interpreter会连dance也一并加到eigenclass里面。看Ruby的源代码,extended和included仅仅可以通知事件的发生,而实际的extend和include操作在这之前就已经完成了。

再多想一步,能不能让一个class只include一个module里面的某些方法,而不是全部方法呢?像这样写。

module MyModule
  def self.extended(base)
    base.include Include
  end
  def dance; puts "dancing"; end
  module Include
    def sing; puts "lalala"; end
  end
end

class MyClass
  extend MyModule
end

对不起,不行。因为include是私有方法,所以base.include是会报错的。还必须这样写。

module MyModule
  def self.extended(base)
    class << base
      alias :old_include :include
      def include(m)
        old_include m
      end
    end
    base.include Include
  end
  def dance; puts "dancing"; end
  module Include
    def sing; puts "lalala"; end
  end
end

class MyClass
  extend MyModule
end

所以,总结一下:

  1. 若是一个class不想extend一个module里面的全部方法,不能改extended,写是要用included去hook,然后base.extend一个子module。而且这个class所生成的object还会额外得到一些新的实例方法(从include的module里面来)。
  2. 若是一个class只想include一个module里面的一部分方法,要先用wrapper把include变成public的,然后再把extended改掉。当然,这个方法会让class得到一些额外的class method。

最后当然是吐槽时间啦,不然我写这么多东西干什么呢(摊手)。这个奇技淫巧是很不错,但是它把include的语义给改变(扩展)了。一般来说看到inlcude,想到的当然是把一个module里面的方法加到实例方法列表中。有了这个技巧之后,真正的意图却是给一个class加singleton method,可能再附送一些用不着的实例方法,挺让人吐血的。

最后再发一个免责声明:本人Ruby小白,拍砖请从轻。


0

   

0

IT 牛人博客聚合网站(udpwork.com) 聚合
|
评论: 0
|
10000+ 本编程/Linux PDF/CHM 电子书下载

from IT牛人博客聚合网站: http://www.udpwork.com/item/7567.html

Written by cwyalpha

六月 23, 2012 在 4:53 上午

发表在 Uncategorized

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

%d 博主赞过: