在我的项目Bar
中,我有这个类Foo
,其实例代表唯一的,命名的真实世界对象。这些实例的引用分散在我项目中的数据结构周围,但是,我还决定通过它们的名称来访问它们。为此,Foo类本身跟踪其实例,如
module Bar
class Foo
attr_reader :name
def initialize( name )
@name = name
end
def self.new *args, &block
new_instance = super
n_i_name = new_instance.name
( @instances ||= {} ).merge! new_instance => n_i_name
return new_instance
end
def inspect; "Foo instance #{name}" end
end
end
现在这是一种常见的模式。通常,要访问实例,可以在Foo
:
class << Bar::Foo
def instance( i )
case i
when self then i
else @instances.rassoc( i ).first end
end
end
i = Bar::Foo.new "John Smith"
#=> Foo instance John Smith
i.object_id
#=> 68997470
Bar::Foo.instance( "John Smith" ).object_id
#=> 68997470
但问题是,Bar
模块下有命名实例的类比类,例如Bar::Baz
,Bar::Quux
等等,需要访问Foo
实例和名称彼此。所以我认为按照名称访问每个其他实例的方式保持顺序是Bar
模块本身的责任,我在其中创建了公共模块方法:
module Bar
# Foo method blah blah blah...
def self.Foo( i ); Foo.instance i end
# Baz method blah blah blah...
def self.Baz( i ); Baz.instance i end
# Quux method blah blah blah...
def self.Quux( i ); Quux.instance i end
end
每当班级Foo
,Baz
,Quux
相互引用时,他们都会使用Bar.Foo( "John Smith" )
样式调用,这也可以通过其唯一名称引用这些实例。现在我的问题是,这对我来说似乎仍然不是100%的犹太人。当我运行rdoc
为Bar
模块创建文档时,公共类方法#Foo
,#Baz
,#Quux
将其添加到文档中。但这些并不是真正意图成为用户界面的一部分。所以我有以下选项,每个选项都有问题:
在用户界面中加入#Foo
,#Baz
,#Quux
。 问题:用户并不真正需要它们;我不打算在UI中设置它们。
向他们添加# :nodoc:
指令,以防止rdoc
记录他们。 问题:感觉不对。它与Bar.Foo
不同,并且朋友被排除在用户界面之外。感觉更像是他们仍然是UI的一部分,但没有文档,秘密。我不希望这样。
使用#private_class_method
将其声明为私有。但是,即使实例#Foo
,#Baz
,#Quux
在正常操作期间按名称相互访问,它们也必须使用Bar.send :Foo, "John Smith"
样式。
问题:选项3似乎最无害。但是,它仍然不完美。理想情况下,我希望以这种方式保护方法Bar.Foo
,Bar.Baz
,Bar.Quux
,这些人可以通过简单地调用Bar.Foo "John Smith"
来通过名称互相调用,而用户必须使用Bar.send :Foo, "John Smith"
,并且不会为用户记录这些模块方法。还有什么其他选择,如果有的话,我必须达到这种状态吗?有没有办法有选择地允许某些类随意使用别人的私有方法?另外,我没有使用受保护的类方法的经验,这可能是一个解决方案吗?感谢您花时间阅读本文。
答案 0 :(得分:1)
查看Understanding private methods in Ruby并搜索SO以获取私人/受保护,有很多材料需要阅读。
受保护的类方法:
class Foo
class << self
def prot
puts "self.prot"
end
protected :prot
end
...
Bar::Foo.prot #=> protected method `prot' called for Bar::Foo:Class (NoMethodError)