这种创建私有类方法是如何工作的:
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
我也发现Ruby(或者至少我对Ruby的了解)不够到位
在这个地区。举个例子,下面是我想要的,但很笨拙,
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
My problems with the code above is that the Ruby syntax requirements
and my code quality metrics conspire to made for cumbersome code.
To have the code both work as I want and to quiet the metrics, I must
make compare() a class method. Since I don't want it to be part of
the class' public API, I need it to be private, yet 'private' by
itself does not work. Instead I am force to use 'private_class_method'
or some such work-around. This, in turn, forces the use of
'self.class.send(:compare...' for each variable I test in '==()'.
Now that's a bit unwieldy.
我也发现Ruby(或者至少我对Ruby的了解)不够到位
在这个地区。举个例子,下面是我想要的,但很笨拙,
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
My problems with the code above is that the Ruby syntax requirements
and my code quality metrics conspire to made for cumbersome code.
To have the code both work as I want and to quiet the metrics, I must
make compare() a class method. Since I don't want it to be part of
the class' public API, I need it to be private, yet 'private' by
itself does not work. Instead I am force to use 'private_class_method'
or some such work-around. This, in turn, forces the use of
'self.class.send(:compare...' for each variable I test in '==()'.
Now that's a bit unwieldy.
如果你在显式对象(在你的例子中是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的所有即将出现的实例方法切换私有访问,但继续在另一个类上声明单例方法,即单例类。