如何在Ruby中实现私有内部类

时间:2016-09-27 05:42:34

标签: ruby class private-class

来自Java,我试图在Ruby中实现LinkedList。我在Java中实现它的通常方法是使用一个名为LinkedList的类和一个名为Node的私有内部类,LinkedList的每个对象都作为Node对象。

class LinkedList
  private
  class Node
    attr_accessor :val, :next
  end
end

我不想将Node类暴露给外部世界。但是使用Ruby中的这个设置,我可以使用这个 -

访问LinkedList类之外的私有Node类对象
node = LinkedList::Node.new

我知道,使用Ruby 1.9,我们可以使用private_constant方法将Node指定为私有常量。但我想知道这是否是实现这一目标的正确方法?另外,为什么我能够在LinkedList类之外创建Node对象,即使它被声明为私有?

2 个答案:

答案 0 :(得分:8)

  

为什么我能够在LinkedList类之外创建Node对象,即使它被声明为私有?

因为在ruby常量中忽略"常规"能见度修饰语。无论他们处于哪个部分,他们都会一直公开。要将其设为私有,请使用private_constant。称之为不合适的设计或其他任何设计,但这就是它的原理。

另外,请注意,即使使用private_constant,私密性也意味着很少。基本上,它唯一能做的就是从列表(LinkedList.constants)和直接解析(LinkedList::Node)中隐藏常量。如果知道名称,他们能够访问它。

class LinkedList
  class Node
    attr_accessor :val, :next
  end

  private_constant :Node
end

LinkedList.const_get('Node') # => LinkedList::Node

答案 1 :(得分:3)

我知道塞尔吉奥的答案绰绰有余,但只是回答了这个问题:

  

如何在Ruby中实现私有内部类

您可以同时使用:

class LinkedList
  class << self
    class Node
    end

    def some_class_method
      puts Node.name
    end
  end
end

LinkedList.some_class_method        # accessible inside class
#=> #<Class:0x007fe1e8b4f718>::Node
LinkedList::Node                    # inaccessible from outside
#=> NameError: uninitialized constant LinkedList::Node
LinkedList.const_get('Node')        # still inaccessible
#=> NameError: uninitialized constant LinkedList::Node

当然,您可以使用

访问Node
LinkedList.singleton_class::Node
#=> #<Class:0x007fe1e8b4f718>::Node

它也可以在LinkedList的单例类常量中使用:

LinkedList.singleton_class.constants
#=> [:Node, :DelegationError, :RUBY_RESERVED_WORDS, :Concerning]

我通常使用private_constant,但这是拥有私人课程的另一种方式。