在我的项目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
, 。问题:用户并没有那么迫切地需要它们;我的设计意图不是让它们出现在 UI 中。#Quux
向它们添加
# :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"
,并且这些模块方法没有为用户记录。我还需要哪些其他选择(如果有的话)来实现这种状态?有没有办法选择性地允许某些类随意使用其他人的私有方法?另外,我对受保护的类方法没有经验,这可能是一个解决方案吗?感谢您花时间阅读本文。