【发布时间】:2011-03-30 14:31:32
【问题描述】:
我是 Ruby 新手(熟悉 Python、C++ 和 C)。我需要创建一个仅由模块中的其他类和方法使用的类。在 Python 中,我只称它为 __classname。我会在 C++ 中使用空的 typedef。我如何在 Ruby 中做到这一点(或者我是在找错树,而不是按照“Ruby 方式”做到这一点?)
【问题讨论】:
我是 Ruby 新手(熟悉 Python、C++ 和 C)。我需要创建一个仅由模块中的其他类和方法使用的类。在 Python 中,我只称它为 __classname。我会在 C++ 中使用空的 typedef。我如何在 Ruby 中做到这一点(或者我是在找错树,而不是按照“Ruby 方式”做到这一点?)
【问题讨论】:
要意识到的最重要的事情是,一个类并没有什么特别之处。它只是一个对象。按照惯例,类被分配给常量,但没有什么说它们必须。
由于类与任何其他对象一样只是对象,因此您将它们设为私有就像将任何其他对象设为私有一样。
以下是我能想到的可能性,按照私密性增加的顺序排列:
my_awesome_library → MyAwesomeLibrary),但一般来说,嵌套在该命名空间下的所有内容都是被认为是私人的。事实上,除了Test::Unit::TestCase,我想不出一个真正期望客户端代码使用的三层深度命名空间的例子。MyAwesomeLibrary::Internal::FfiStruct
:nodoc: RDoc 标签标记。snake_case 约定就是这样:约定。)send 似乎比 instance_variable_get 更广泛地使用,这就是为什么我认为实例变量比方法具有更高级别的隐私。Module.new、Class.new 或Module#define_method。例如:
module MyAwesomeLibrary
struct = Class.new(FFI::Struct) do
# ...
end
PublicInterface = Class.new do
define_method(:initialize) do |bar|
@foo = struct.new(bar)
end
end
end
是的,这是在 Ruby 中实现真正 100% 信息隐藏和封装的唯一方法。
然而,普通的 Ruby 方法是简单地将这些东西记录为私有的(也许将其降低到命名空间的级别)并信任您的开发人员。在 Ruby 社区中,这有时被概括为 Python 口号“我们都是自愿的成年人”。
【讨论】:
直接从this blog post 获取此信息,但从 Ruby 1.9.3 开始,您可以使用 private_constant 在模块内创建私有类:
class Person
class Secret
def to_s
"1234vW74X&"
end
end
private_constant :Secret
def show_secret
Secret.new.to_s
end
end
【讨论】:
到目前为止,我还没有在 Ruby 中看到过这样的概念,但我想你可以通过创建私有方法来模拟它,该方法将返回一个作为局部变量创建的类(请记住,在 Ruby 中,类是一个对象,就像任何其他,并且可以在方法中实例化并由它返回)。
顺便说一句,即使是 Ruby 中的私有方法也不像其他语言那样私有 - 您始终可以使用 send 方法访问它们。但这样做意味着您知道自己在做什么。
【讨论】:
attr_accessor 方法)轻松覆盖的功能添加语言结构将是骇人听闻的。我非常感谢 Ruby 的这种简单性,尽管我会删除更多的关键字(比如完全多余的 for)。关于函数调用,我同意你的看法。顺便说一句,我很确定可以很容易地将私有类“包装”到单个方法调用中,因此至少它不应该看起来 hackish。 :)