这种创建私有类方法是如何工作的:

class Person

  def self.get_name
    persons_name
  end

  class << self

    private

    def persons_name
      "Sam"
    end
  end
end

puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name  #=> raises "private method `persons_name' called for Person:Class (NoMethodError)"

但这不是:

class Person

  def self.get_name
    persons_name
  end

  private

  def self.persons_name
    "Sam"
  end
end

puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name

当前回答

如果你在显式对象(在你的例子中是self)上定义一个方法,Private似乎不起作用。您可以使用private_class_method将类方法定义为私有的(或者像您描述的那样)。

class Person
  def self.get_name
    persons_name
  end

  def self.persons_name
    "Sam"
  end

  private_class_method :persons_name
end

puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name

或者(在ruby 2.1+中),因为方法定义返回方法名的符号,你也可以这样使用:

class Person
  def self.get_name
    persons_name
  end

  private_class_method def self.persons_name
    "Sam"
  end
end

puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name

其他回答

ExiRe写道:

ruby的这种行为真是令人沮丧。我的意思是如果你移动 以私室自居。方法,那么它不是私有的。但是,如果 你把它移到类<< self,然后它突然工作了。 这太恶心了。

它可能令人困惑,可能令人沮丧,但绝对不会令人恶心。

一旦你理解了Ruby的对象模型和相应的方法查找流,这就非常有意义了,尤其是考虑到private不是一个访问/可见性修饰符,而是一个方法调用(类作为它的接收者),就像这里讨论的那样……在Ruby中没有所谓的“私有部分”。

要定义私有实例方法,您可以在实例的类上调用private来将随后定义的方法的默认可见性设置为private…因此,通过在类的类上调用private来定义私有类方法是非常有意义的。它的元类。

其他主流的、自称为OO的语言可能会提供不那么令人困惑的语法,但在没有Ruby元编程功能的情况下,你肯定会牺牲掉一个令人困惑且不太一致(不一致?)的对象模型。

为了完整起见,我们还可以避免在单独的行中声明private_class_method。我个人不喜欢这种用法,但很高兴知道它的存在。

private_class_method  def self.method_name
 ....
end

默认情况下,所有类方法都是公共的。为了使它们私有,你可以使用模块#private_class_method,就像@tjwallace写的那样,或者像你所做的那样定义它们:

class << self

  private

  def method_name
    ...
  end
end

类<< self打开了self的单例类,这样就可以为当前self对象重新定义方法。这是用来定义类/模块(“静态”)方法。只有在这里,定义私有方法才能真正提供私有类方法。

如果你在显式对象(在你的例子中是self)上定义一个方法,Private似乎不起作用。您可以使用private_class_method将类方法定义为私有的(或者像您描述的那样)。

class Person
  def self.get_name
    persons_name
  end

  def self.persons_name
    "Sam"
  end

  private_class_method :persons_name
end

puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name

或者(在ruby 2.1+中),因为方法定义返回方法名的符号,你也可以这样使用:

class Person
  def self.get_name
    persons_name
  end

  private_class_method def self.persons_name
    "Sam"
  end
end

puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name

实例方法在类定义块中定义。类方法定义为类的单例类上的单例方法,也非正式地称为“元类”或“特征类”。private不是关键字,而是一个方法(Module#private)。

这是一个对方法self#private/ a# private的调用,它将为所有即将到来的实例方法定义“切换”私有访问,直到切换到其他方式:

class A
  private
    def instance_method_1; end
    def instance_method_2; end
    # .. and so forth
end

如前所述,类方法实际上是定义在单例类上的单例方法。

def A.class_method; end

或者使用特殊的语法打开a的匿名单例类的定义体:

class << A
  def class_method; end
end

类A中的“message private”- self -的接收者是类对象A。

下面的示例实际上调用了两个称为private的不同方法,为调用使用了两个不同的接收者或目标。在第一部分中,我们定义了一个私有实例方法(“在类a上”),在后者中,我们定义了一个私有类方法(实际上是a的单例类对象上的一个单例方法)。

class A
  # self is A and private call "A.private()"
  private def instance_method; end

  class << self
    # self is A's singleton class and private call "A.singleton_class.private()"
    private def class_method; end
  end
end

现在,重写一下这个例子:

class A
  private
    def self.class_method; end
end

你能看出Ruby语言设计者所犯的错误吗?您为A的所有即将出现的实例方法切换私有访问,但继续在另一个类上声明单例方法,即单例类。