Reputation: 5594
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
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!
Upvotes: 5
Views: 1746
Reputation: 258228
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.
Upvotes: 3