Ruby 新手学习钩子方法中遇到的问题,请高手赐教

neverlandxy_naix · 2012年11月09日 · 最后由 skandhas 回复于 2012年11月09日 · 4009 次阅读

最近在学习 Ruby 中的钩子方法,有一个地方没有弄明白,自己也没有 google 到解决办法,麻烦高手赐教。 书中有这么一段话: 当为任意类或模块定义一个名为 method_added 的方法,它将在为该类或模块定义一个实例方法时被调用。 值得注意的是,method_added 类方法会被该类的子类所继承。但是这个钩子方法没有任何类信息的参数,所以在添加某个方法时,无法知道是定义 method_added 方法所在的类添加的,还是它的某个子类所添加的。解决该问题的一个方法是为定义 method_added 的类同时定义 inherited 钩子方法,然后这个 inherited 方法为每个子类定义一个 method_added 方法。 我是这么定义的,这种方法可以正确的输出其子类和子类定义的方法 Ruby 版本是 187

def String.inherited(klass)
  klass.instance_eval do
    def method_added(name)
      puts "#{self} added a method #{name}"
    end
  end
end

class SubClass < String
  def a_method; end
end
# => SubClass added a method a_method

但是我按如下的方法定义后,就没有任何输出,实在是没弄明白哪里错了,麻烦大家指点下,谢谢。

def String.inherited(klass)
  klass.instance_eval do
    define_method :method_added do |name|
      puts "#{klass} added a method #{name}"
    end
  end
end

class SubClass < String
  def a_method; end
end

define_method => define_singleton_method

@jjym 我换试试,187 里面没有 define_singleton_method 方法

define_method 不是钩子函数吧。

@jjym 还是不行,没有任何输出 @chenge define_method 不是钩子函数,就是说这句 define_method 就不执行了吗?

192 用 define_singleton_method 有输出。 我可能说得不对,methed_added 是钩子,define_method 是动态方法。为何没输出,我不知道。

简单从 Ruby 层面说吧: 第一段代码

klass.instance_eval do
  def method_added(name)
    puts "#{self} added a method #{name}"
  end
end

相当于

def kass.method_added(name)
    puts "#{self} added a method #{name}"
end

在这里相当于

def SubClass.method_added(name)
    puts "#{self} added a method #{name}"
end

第二段代码

klass.instance_eval do
  define_method :method_added do |name|
    puts "#{klass} added a method #{name}"
  end
end

define_method 的含义是"Defines an instance method in the receiver. "

等价于

klass.instance_eval do
  self.send :define_method, :method_added do |name|
    puts "#{klass} added a method #{name}"
  end
end

相当于

class SubClass 
  define_method :method_added do |name|
      puts "#{klass} added a method #{name}"
    end
end

p SubClass.instance_methods

@skandhas 明白了,谢谢指点^_^

#7 楼 @neverlandxy_naix 不客气,能帮上忙就好。其实我上面说的比较笼统,再详细的你可以查阅相关资料即可。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号