On 22/05/05, Thomas <sanobast-2005a / yahoo.de> wrote: > Hi folks, > > I recently tried to implement a uniform vector class being defined as a > vector the elements of which all comply to some kind of common interface > or are a subclass of some prototype class. > > My first naive approach was to inherit from Array and to overwrite some > methods to make sure that new elements are ok. This works fine for > methods like []=, <<, or unshift but when implementing + I ran into the > following problem: Array#+ returns an Array and not a Vector which is > why I have to create a new Vector from the result of Array#+. As Array#+ > already creates a new Array, this probably isn't very efficient and I > don't like the idea of having to do this for all possible methods that > return an Array. I was hoping to be able to somehow limit my > modifications of Array to a few essential methods. > > So, the question is: Does somebody know a way to make sure that methods > returning an Array (+, &, -, * etc.) always return a Vector without > having to redefine each of them? > > Please find my current toy implementation down below. > Hello Thomas, I'm quite shure you don't need to do what you are doing, because this violates duck typing, but if you really want to you can use something like the below. Here I don't inherit from an array, but forward to an array, which often is the simpler approach. Please rethink your design. If you really want to do this for speed, you could implement a simple C extension that includes a numeric array, or use the narray class. Otherwise just don't put anything wrong into the array, and everything will work out fine. And if someone wants to put something into the array that quacks like a duck but is no duck, also everything will continue to work. best regards, Brian class Vector def initialize(*args) @numbers = args check_values(args) end def method_missing(method, *args, &block) result = @numbers.send(method, *args, &block) if result.is_a?Array Vector.new(*result) else result end end private def check_values(values) return true if @numbers.empty? and values.empty? unless defined?(@protoclass) prototype = @numbers[0] || values[0] @protoclass = prototype.class end values.each do |e| unless e.kind_of?(@protoclass) raise TypeError, "Expected #{@protoclass} but got #{e.class}", caller[2..-1] end end end end if __FILE__ == $0 v = Vector.new # these are okay p v v << 1 p v v[1] = 2 p v p (v + [1,2,3]) v += [1,2,3] p v v.unshift(3) p v # but this should throw an error (that's what this is all about) v << "a" p v end -- http://ruby.brian-schroeder.de/ Stringed instrument chords: http://chordlist.brian-schroeder.de/