I have the need to use a Stack-like data structure for a program that I am writing and I know that Ruby doesn't have an explicit Stack data-structure, but that the Array class has all of the properties that make a Stack: push
, pop
, size
, clear
, isEmpty
, inspect
, to_s
.
In searching online I found various posts using this syntax to extract features of the Array class into a subclass:
Stack = Array.extract([
:push,
:pop,
:size,
:clear,
:inspect,
:to_s
])
s = Stack.new
s.push 1
s.push 2
s.push 3
s # => [1, 2, 3]
s.pop # => 3
s # => [1, 2]
I would like to do something similar to this so my subclass of Array is restricted in what calls it can make, but it appears that the extract method is no longer in the Array class API.
Questions:
- This feature was removed for a reason, what is the detriment of something like this?
- How can achieve functionality similar to this using Ruby 1.9.3? Right now I am just delegating the calls that I need to the Array class, but all the other methods in the Array class can still be called on my Stack object, which I don't want to allow.
Take this code, for example:
Here you have private instance var to which you delegate selected methods. Other methods cannot be called directly. The syntax can be sweetened and made more "rubesque" with some metaprogramming, but basic idea is as shown above.
Of course, one can always get to that private var via
instance_variable_get
and there's nothing you can do about it. This is Ruby!Make clean safe public interface. And if someone tries to meddle with inner parts and breaks something, it's his problem.
Update
If you're using ActiveSupport (which comes with Rails), then there's a simpler way of doing this.
Or look at similar answer by @AndrewGrimm.
Maybe you can undefine methods that you don't like, although it looks wired.
If you're going to be doing a lot of delegating, then you may want to use the delegation methods Ruby provides.
Not only does it mean less typing, but if you're familiar with
Forwardable
, it's easier to read. You know that your class is merely delegating, without having to read the code forStack#push
orStack#pop
.