David Masover
9/25/2008 2:10:00 AM
On Wednesday 24 September 2008 15:45:13 Kyle Schmitt wrote:
> I'm wondering what the _right_ way is to go about getting the right
> class with inheritance and super()
Maybe it's just me, but I often use encapsulation, instead.
> The issue is that while << works fine, the results from + and - return
> an Array, not a FixedSizeArray, UNLESS I run the returned value
> through a FixedSizeArray.new(), and somehow, that just seems wrong and
> wasteful.
I would guess it's a result of C code making assumptions (Array is Core stuff,
after all, so a lot of C) -- maybe something doing the equivalent of
Array.new, rather than self.class.new.
With an encapsulated pattern, though, you'd at least be avoiding a new Array
object each time:
class FixedSizeArray
def initialize(size=1,fill=nil)
# Old duck-typing habit: kind_of, not is_a
if size.kind_of? Array
@array = size # Not duplicated -- careful.
else
@array = Array.new(size, fill)
end
# Why return self here? FixedSizeArray.new will always
# return the new object. Return value here is ignored.
end
def size=(newsize)
# No need to check length==newsize, really
if @array.length > newsize
@array.slice!(Range.new(0,length-newsize-1))
elsif @array.length < newsize
@array.unshift(*Array.new(newsize-length){0})
end
size
end
def <<(data)
@array.shift
@array << data
self
end
def -(data)
self.class.new((@array -
data).unshift(*Array.new(size-super(data).length,nil)))
end
def +(data)
# No need for Range; slice will take two arguments
self.class.new((@array + data).slice(data.length,@array.size+data.length))
end
# Add some array-ness
include Enumerable
def each *args, &block
@array.each *args, &block
end
end
I have no idea which will be more efficient, though.
Also, does this graphing tool need to be fast? If not -- if I understand what
you're trying to do -- you might consider simply shrinking it down to size
(with a single slice call) when you need it. One line is a lot easier to
write than a whole class.