Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement private inner class in Ruby

Coming from Java, I am trying to implement LinkedList in Ruby. The usual way I would implement this in Java is have an class called LinkedList and private inner class called Node with each object of LinkedList as Node object.

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

I do not want to expose the Node class to external world. However with this setup in Ruby, I can access the private Node class object outside the LinkedList class using this -

node = LinkedList::Node.new

I know, with Ruby 1.9, we can use private_constant method to designate Node as private constant. But I am wondering if this is the right way to accomplish this? Also why am I able to create Node objects outside the LinkedList class even though it is declared as private?

like image 719
WastedPandoo Avatar asked Sep 27 '16 05:09

WastedPandoo


People also ask

How do you make a class private in Ruby?

The classic way to make class methods private is to open the eigenclass and use the private keyword on the instance methods of the eigenclass — which is what you commonly refer to as class methods.

How do you access private inner class with reflection?

Yes, you can instantiate a private inner class with Java reflection. To do that, you need to have an instance of outer class and invoke the inner class constructor which will use outer class instance in its first argument. @popgalop Inner classes are the same as methods.

Can inner class access private variables?

It can access any private instance variable of the outer class. Like any other instance variable, we can have access modifier private, protected, public, and default modifier.


1 Answers

why am I able to create Node objects outside the LinkedList class even though it is declared as private?

Because in ruby constants ignore "regular" visibility modifiers. They're always public, regardless of which section they're in. To make them private, use private_constant. Call this inelegant design or whatever, but that's how it is.

Also, be warned that even with private_constant, the privateness means very little. Basically, the only thing it does is hide the constant from lists (LinkedList.constants) and direct resolution (LinkedList::Node). If one knows the name, they will be able to access it.

class LinkedList
  class Node
    attr_accessor :val, :next
  end

  private_constant :Node
end

LinkedList.const_get('Node') # => LinkedList::Node
like image 179
Sergio Tulentsev Avatar answered Oct 14 '22 09:10

Sergio Tulentsev