4

我 ruby​​ 1.8.7,为什么我可以在 main 中使用 require,但不能使用 self.require?

require('date') # ok
self.require('date') 
NoMethodError: private method `require' called for main:Object
from (irb):22
from /usr/lib/ruby/1.8/date.rb:437

众所周知,main 是 Object 类:irb(main):045:0> self => main

irb(main):043:0> self.class
=> Object

但我发现它有内核混合:

irb(main):042:0> self.class.included_modules
=> [Kernel]

此外,我发现 require 是 self 的私有方法:

irb(main):037:0> self.private_methods
=> [... "require", ...]

同样,我不能使用 self.attr_accessor:

irb(main):051:0> class X
irb(main):052:1> self.attr_accessor(:ssss)
irb(main):053:1> end
NoMethodError: private method `attr_accessor' called for X:Class
from (irb):52
from /usr/lib/ruby/1.8/date.rb:437

它是怎么发生的?有人可以澄清这些问题吗?

4

3 回答 3

2

检查以下简单示例:

class Person
  def initialize(age)
    @age = age
  end

  def compare_to(other)
    # we're calling a protected method on the other instance of the current class
    age <=> other.age
  end

  # it will not work if we use 'private' here
  protected

  def age
    @age
  end
end

在 ruby​​ 中,我们有隐式和显式方法接收器,检查下一个代码片段:

class Foo
  def a; end

  # call 'a' with explicit 'self' as receiver
  def b; self.a; end

  # call 'a' with implicit 'self' as receiver
  def c; a; end
end

基本上在红宝石中,如果一个方法是private它只能在implicit接收器上调用(没有self关键字)。在您的示例require中,是一个private定义Kernel模块的方法,它只能在implicit主题上调用。

于 2012-04-25T12:39:25.550 回答
2

require是私有方法。所以你不能把它称为

Object.require 'date'

但是你可以用 ruby​​ 的 eval/send 方法来调用它:

Object.send(:require, 'date')
# or
self.send(:require', 'date')

实际上非常相似的是

require 'date'

例如pry 控制台会将其解释为

instance_exec do
  require 'date'
end

我相信 Ruby 解释器会做几乎相同的事情。它将任何顶级命令作为一个instance_exec块传递给Object,它可以调用任何私有方法。

于 2012-04-25T12:52:00.150 回答
0

私有方法只能使用隐式接收器调用。这意味着require将起作用,但self.require不会。

可以在 上调用受保护的方法self,并且可以在任何对象上显式调用公共方法。

这些是唯一的限制。是的,您可以在子类中使用私有方法,并且send会绕过所有访问控制。

于 2012-04-25T13:28:37.940 回答