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

c47*_*57p 16 ruby oop private class

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

Jör*_*tag 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.new,Class.newModule#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
Run Code Online (Sandbox Code Playgroud)

是的,这是在Ruby中实现真正的100%信息隐藏和封装的唯一方法.

但是,正常的Ruby方式是简单地将这些东西记录为私有(可能会将其命名为命名空间),并相信您的开发人员.在Ruby社区中,有时会在Python口号"我们都同意成年人"中对此进行总结.


ace*_*reg 10

直接从这篇博客文章中获取这些信息,但是从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
Run Code Online (Sandbox Code Playgroud)


Mla*_*vić 4

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

顺便说一句,即使 Ruby 中的私有方法也不像其他语言那样私有 - 您始终可以使用send方法访问它们。但这样做意味着你知道自己在做什么。