这种创建私有类方法是如何工作的:
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
ExiRe写道:
ruby的这种行为真是令人沮丧。我的意思是如果你移动
以私室自居。方法,那么它不是私有的。但是,如果
你把它移到类<< self,然后它突然工作了。
这太恶心了。
它可能令人困惑,可能令人沮丧,但绝对不会令人恶心。
一旦你理解了Ruby的对象模型和相应的方法查找流,这就非常有意义了,尤其是考虑到private不是一个访问/可见性修饰符,而是一个方法调用(类作为它的接收者),就像这里讨论的那样……在Ruby中没有所谓的“私有部分”。
要定义私有实例方法,您可以在实例的类上调用private来将随后定义的方法的默认可见性设置为private…因此,通过在类的类上调用private来定义私有类方法是非常有意义的。它的元类。
其他主流的、自称为OO的语言可能会提供不那么令人困惑的语法,但在没有Ruby元编程功能的情况下,你肯定会牺牲掉一个令人困惑且不太一致(不一致?)的对象模型。
Ruby似乎提供了一个糟糕的解决方案。要解释,先从简单的说起
c++示例,显示了对私有类方法的访问:
#include <iostream>
class C
{
public:
void instance_method(void)
{
std::cout << "instance method\n";
class_method(); // !!! LOOK !!! no 'send' required. We can access it
// because 'private' allows access within the class
}
private:
void static class_method(void) { std::cout << "class method\n"; }
};
int main()
{
C c;
c.instance_method(); // works
// C::class_method() does not compile - it's properly private
return 0;
}
运行上述程序
% ./a.out
instance method
class method
现在Ruby似乎没有提供类似的功能。我认为,Ruby的规则是这样的
接收方不能访问私有方法。也就是说,
inst.pvt_method # FAILS
pvt_method # WORKS only within the class (good)
这对于私有实例方法是可以的,但是对于私有类就会产生问题
方法。
我希望Ruby是这样工作的:
class C
def instance_method
STDOUT << "instance method\n"
# Simple access to the private class method would be nice:
class_method # DOES NOT WORK. RUBY WON'T FIND THE METHOD
C.class_method # DOES NOT WORK. RUBY WON'T ALLOW IT
# ONLY THIS WORKS. While I am happy such capability exists I think
# the way 'send' should be used is when the coder knows he/she is
# doing a no-no. The semantic load on the coder for this is also
# remarkably clumsy for an elegant language like ruby.
self.class.send(:class_method)
end
private_class_method def self.class_method() STDOUT << "class method\n"; end
end
但是,遗憾的是,上述方法并不奏效。有人知道更好的办法吗?
当我看到'发送'之前的方法,这是一个明显的迹象,代码违反
API的设计者的意图,但在这种情况下,设计是特别的
要使类的实例方法调用私有类方法。
如果你在显式对象(在你的例子中是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元编程功能的情况下,你肯定会牺牲掉一个令人困惑且不太一致(不一致?)的对象模型。