新手问题 关于 Object#extend 的疑问

ZumiKua · 2014年08月20日 · 最后由 lihaidong 回复于 2014年08月21日 · 2084 次阅读
module Bar
  def abc   
   define_method(:test){p "test"}
  end
end

class Foo
  extend Bar
  abc
end
Foo.new.test

这段代码运行正常

module Bar
  def abc   
   self.define_method(:test){p "test"} #private method called
  end
end

class Foo
  extend Bar
  abc
end
Foo.new.test

这段代码会报 private method called

我自己 p 了一下 self 的值,为 Foo 所以我做了一个推论,运行正常的代码中调用的是 Bar 模块的 define_method,但是这样的话新增的 test 方法应该是加到 Bar 上,Foo 并没有 include Bar,为什么却能够拥有 Bar 的实例方法呢? 还有 Bar 的 abc 已经被 extend 到了 Foo 之中,为什么调用 Foo 的私有方法还是会报错呢?

望解答

define_method 是私有的,Ruby 的私有方法只能通过无点方式或者 send 方式调用,和在哪调用没关系 (这和 C++/Java 的私有方法区别很大)

class Foo; end

class << Foo
  Foo.define_method :bar do; end # private method called
  self.define_method :bar do; end # private method called
  define_method :bar do; end # 不加点调用就没事
end

#1 楼 @luikore 原来是这样! 感谢您清晰简明的解释。

define_method 是 Module 私有方法,子类调用父类的私有方法,很微妙,加 self 则 private method called,不加则 ok,如:

class A
    def a
        puts "class A 's method a"
    end
    private :a
end

class B < A
    def b
        a
    end
end

B.new.b # class A 's method a

class C < A
    def c
        self.a
    end
end

C.new.c # private method called
需要 登录 后方可回复, 如果你还没有账号请 注册新账号