Ruby模块中的私有类(不是类方法)?

时间:2010-08-16 18:53:41

标签: ruby oop class private

我是Ruby新手(熟悉Python,C ++和C)。我需要创建一个只能由模块中的其他类和方法使用的类。在Python中,我只是将其称为__classname。我在C ++中使用一个空的typedef。我如何在Ruby中执行此操作(或者我是在咆哮错误的树而不是“Ruby方式”?)

3 个答案:

答案 0 :(得分:27)

最重要的是要认识到一堂课并不特别。这只是一个对象。按照惯例,类被分配给常量,但没有任何内容表明它们

由于类只是像任何其他对象一样的对象,因此您将它们设置为私有,就像将任何其他对象设为私有一样。

以下是我可以想到的可能性,按照增加私密性的顺序:

  1. 将它们嵌套在命名空间(即模块)中。在Ruby中,通常期望所有库的模块和类都位于名称空间内,并且名称与库的名称相同(即my_awesome_libraryMyAwesomeLibrary),但通常情况下,嵌套在下面的所有内容该命名空间被认为是私有的。实际上,除了Test::Unit::TestCase之外,我想不出客户端代码实际预期会使用的三级深命名空间的单个示例。
  2. 与1.相同,但将其命名为明显的,例如MyAwesomeLibrary::Internal::FfiStruct
  3. 与1.或2.相同,并使用:nodoc: RDoc标记进行标记。
  4. 类似于3.,但使用更现代的文档系统,如YARD,它实际上允许您明确标记私有API。
  5. 使用方法而不是常量。方法可以是私有的。 (为了保持一致性,您可以让方法名称以大写字母开头,使其类似于常量。没有什么可以阻止的,snake_case约定只是:约定。)
  6. 使用实例变量。他们总是私密的。请注意,可以使用反射轻松访问私有方法和实例变量。 send似乎比instance_variable_get更广泛地使用,这就是为什么我认为实例变量具有比方法更高级别的隐私。
  7. 实际上获取实际隐私或封装的唯一方法是使用局部变量和闭包。但请注意,这可能会妨碍您使用Ruby的模块,类或方法定义语法,因为这些会创建新的范围。在您需要访问课程的所有情况下,您需要使用Module.newClass.newModule#define_method
  8. 例:

    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口号“我们都同意成年人”中对此进行总结。

答案 1 :(得分:10)

直接从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

答案 2 :(得分:4)

到目前为止,我还没有在Ruby中看到过这样的概念,但我想你可以通过创建私有方法来模拟它,这将返回一个创建为局部变量的类(请记住,在Ruby中,类是一个对象就像任何一个其他,可以在方法中实例化并由它返回。)

BTW,即使Ruby中的私有方法也不像其他语言那样私密 - 你总是可以使用send方法访问它们。但这样做意味着你知道自己在做什么。