Writing Ruby Libraries - hiding methods from outside the module
I'm writing a Ruby library which has a module with a bunch of classes inside it. Many of these classes need to be usable and modifiable by calling scripts, but I don't want (some of) the initializers to be visible/callable:
module MyLib
class Control
def initialize
# They can use this开发者_StackOverflow
end
def do_stuff
Helper.new('things')
end
end
class Helper
# Shouldn't be visible
def initialize(what)
@what = what
end
def shout
@what
end
end
end
c = MyLib::Control.new
h = c.do_stuff
p h.shout
# => "things"
# ^ All of this is desired
# v This is undesirable
p MyLib::Helper.new('!')
# => <MyLib::Helper @what='!'>
If it's a simple thing, then I'd also appreciate the generated RDoc not even include the .new
method for the Helper
class either. Any ideas?
Thanks for reading!
My original answer was completely wrong, as @Matthew pointed out. But there are other workarounds. For instance, you can assign an anonymous class to a class variable on Control
, and still define methods as normal by using class_eval
:
module MyLib
class Control
def initialize
end
def do_stuff
@@helper.new('things')
end
@@helper = Class.new
@@helper.class_eval do
def initialize(what)
@what = what
end
def shout
@what
end
end
end
end
The snippet
c = MyLib::Control.new
h = c.do_stuff
p h.shout
still writes "things"
, but now there's no way to access @@helper
except through the class variable. If someone really wants to access it my reopening the Control
class or using class_eval
, there's nothing to stop them, but that's just something you have to deal with in a dynamic language.
I chose to assign the anonymous class to a class variable so that it would only be created once; but if you don't care about redefining the anonymous class many times, there's no reason it couldn't be an instance variable.
Ruby has access control.
精彩评论