ruby – 在模块中扩展类方法

前端之家收集整理的这篇文章主要介绍了ruby – 在模块中扩展类方法前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在玩 ruby的元编程功能,我发现它有点毛茸茸.我正在尝试使用模块包装方法调用.目前,我这样做:
module Bar
  module ClassMethods
    def wrap(method)
      class_eval do
        old_method = "wrapped_#{method}".to_sym
        unless respond_to? old_method
          alias_method old_method,method

          define_method method do |*args|
            send old_method,*args
          end
        end
      end
    end
  end

  def self.included(base)
    base.extend ClassMethods
  end
end

class Foo
  include Bar

  def bar(arg = 'foo')
    puts arg
  end

  wrap :bar
end

三个问题:

>如果不重命名方法,有没有办法做到这一点,以便允许使用超级?还是更清洁/更短的东西?
>有没有一种简洁的方法来设置默认值?
>有没有办法移动wrap:bar进一步调用

解决方法

1)更清洁/更短
module ClassMethods
  def wrap(method)
    old = "_#{method}".to_sym
    alias_method old,method
    define_method method do |*args|
      send(old,*args)
    end
  end
end

class Foo
  extend ClassMethods

  def bar(arg = 'foo')
    puts arg
  end

  wrap :bar
end

据我所知,没有重命名就无法实现这一目标.您可以尝试在define_method块中调用super.但首先,如果明确指定参数,则只能在define_method内调用super,否则会收到错误.但即使你打电话,例如super(* args),在该上下文中的self将是Foo的一个实例.所以对bar的调用会转到Foo的超类,找不到并最终导致错误.

2)是的,就像这样

define_method method do |def_val='foo',*rest|
  send(old,def_val,*rest)
end

但是,在Ruby 1.8中,使用define_method中的块是not possible,但这已经修复为1.9.如果您使用1.9,您也可以使用它

define_method method do |def_val='foo',*rest,&block|
  send(old,&block)
end

3)不,不幸的是. alias_method需要存在它作为输入的方法.由于Ruby方法在解析时就已存在,因此必须在bar的定义之后放置wrap调用,否则alias_method会引发异常.

猜你在找的Ruby相关文章