如何创build一个私人类的方法?

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

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 

private似乎并不工作,如果你是一个明确的对象(在你的情况下self定义一个方法)。 您可以使用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.method那么它不是私人的。 但是,如果你把它移到“自我”上,那么它就会突然生效。 这只是恶心。

令人困惑的可能是,令人沮丧的可能是,但令人厌恶的肯定不是。

一旦理解了Ruby的对象模型和相应的方法查找stream程 ,特别是考虑到private 不是访问/可见性修饰符,而是实际上是一个方法调用(将类作为接收者)时 ,这是非常有意义的。在Ruby中没有“私人部分”这样的东西。

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

其他主stream的,自称OO的语言可能会给你一个不那么令人困惑的语法,但是你绝对会将这种情况与Ruby的元编程设施的function相混淆,不太一致(不一致的)对象模型。

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

 class << self private def method_name ... end end 

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

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

 private_class_method def self.method_name .... end 

我也一样,发现Ruby(或者至less是我的知识)在这个领域的标志。 比如下面做我想要的但笨拙的,

 class Frob attr_reader :val1, :val2 Tolerance = 2 * Float::EPSILON def initialize(val1, val2) @val2 = val1 @val2 = val2 ... end # Stuff that's likely to change and I don't want part # of a public API. Furthermore, the method is operating # solely upon 'reference' and 'under_test' and will be flagged as having # low cohesion by quality metrics unless made a class method. def self.compare(reference, under_test) # special floating point comparison (reference - under_test).abs <= Tolerance end private_class_method :compare def ==(arg) self.class.send(:compare, val1, arg.val1) && self.class.send(:compare, val2, arg.val2) && ... end end 

我在上面的代码中遇到的问题是,Ruby语法要求和我的代码质量指标共同造成了繁琐的代码。 为了让代码既能够按照我的需要工作,又能平静度量指标,我必须使用compare()方法。 由于我不希望它是类的公共API的一部分,我需要它是私人的,但“私人”本身是行不通的。 相反,我强迫使用“private_class_method”或一些这样的解决办法。 这反过来又强制使用'self.class.send(:compare …'来表示我在'==()'中testing的每个variables,现在这有点笨拙。

实例方法在类定义块内部定义。 类方法被定义为类的单例类的单例方法,也被非正式地称为“元类”或“本征类”。 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 

“message private”的接收者 – 自我内部class A是类对象A. self在class << A内部class << A块是另一个对象,即单例类。

下面的例子实际上是调用两个不同的方法,称为私人 ,使用两个不同的收件人或目标的电话。 在第一部分中,我们定义了一个私有实例方法(“在类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语言devise师犯的错误吗? 您切换到A的所有即将到来的实例方法的私有访问,但继续在不同的类(单例类)上声明一个单例方法。

截至ruby2.3.0

 class Check def self.first_method second_method end private def self.second_method puts "well I executed" end end Check.first_method #=> well I executed