From: timr Date: 2010-11-01T09:40:15+09:00 Subject: Re: the dark side of inherited methods It is a problem with inheritance and another reason why inheritance is almost never what we want. Tim: Glad that I am not the only one who thinks inheritance has some holes. Tim: Note the corrected output from James Edward Gray II's response: class Vector < Object def initialize(*array) @array = array.flatten end def class ::Vector end def method_missing(meth, *args, &blk) result = @array.send(meth, *args, &blk) if result.object_id == @array.object_id self elsif result.class == ::Array self.class.new(result) else result end end end v = Vector.new(1,2,3) # => # v.class # => Vector v.collect { |item| item * 3 }.class # => Vector v.collect!{ |item| item * 3 }.class # => Vector That's a solution for Ruby 1.9, but a similar trick is possible with 1.8 using a touch more code. It's probably not perfect yet, but you get the idea. Tim: It actually runs fine in 1.8.7 just as you have it coded. Tim: However, I already blew my method_missing to over-ride the mathematical operators (see below): Tim: But I get your approach and I will think about something along those lines. It could also work to set up a proxy class and use its method_missing (since I already used Vector's method_missing) to fix the type returned the way you did. But that means v - Vector.new(1,1,1); p_of_v = Proxy.new(v) every time I want to use a vector. Still not ideal. class Vector < Array undef :-, :+, :*, :== def initialize(*arr) v = super(arr.flatten) end def to_a Array.new(self) end def &(arg) Vector.new(super) end def |(arg) Vector.new(super) end def collect(&blk) Vector.new(super) end def select(&blk) Vector.new(super) end def method_missing(meth, arg) arg.class == Vector ? a2 = arg : a2 = Vector.new(arg) long, short = [self, a2].sort{|s,b| b.length <=> s.length} empty_collection = Array.new(long.length) arr_result = empty_collection.each_with_index.map do |item, ind| if self[ind%self.length] == nil || a2[ind%a2.length] == nil #allow nils to be mathematically processed nil else self[ind%self.length].send(meth, a2[ind%a2.length]) end end Vector.new(arr_result) end end Example Usage: a = Vector.new([1,2,1,10]) b = Vector.new([2,5,1,7]) a - b # => [-1, -3, 0, 3] a.uniq.class # => Vector (a | b) # => [1, 2, 10, 5, 7] (a | b).class # => Vector