On 5/16/07, Dan Zwell <dzwell / gmail.com> wrote:
> Hi, all,
>
> I have subclassed Array to add some features. I am redefining sort_by so
> that it does not return an Array but a Pairs (my subclass), but I cannot
> get the syntax for passing the blocks right.
>
> Here's my code:
>
>    class Pairs < Array
>      def initialize(ary)
>        self.replace(ary)
>      end
>
>      alias_method :sort_by_old, :sort_by
>      # PROBLEM here:
>      def sort_by(&block)
>        ary = self.sort_by_old {yield(block)}
>        Pairs.new(ary)
>      end
>    end
>
> I just want Pairs#sort_by to return a Pairs object every time it is
> called. Could anybody help me?
>
> Thanks,
> Dan
>
>

def sort_by(&block)
   Pairs.new(self.sort_by_old(&block))
end

This should solve your block passing problem.

However, I'd strongly suggets rethinking making a subclass of array
In most cases its better to use delegation to an array instance
variable.

Something like:

require 'forwardable'

class Pairs
      extend Forwardable

      # For methods which you would not have overriden in the subclass
      # simply delegate to the instance variable @array
      # this is just an example, the division between methods which are
      # simply delegated, which are replaced and which are wrapped is up
      # to you.
      def_delegators(:@array, :[], :[]=,  :+ #...

      # I notice that your initialize method doesn't seem to take the same
      # argument as Array so ...
      def initialize(array)
           @array = array
      end
=begin
      # If you wanted to have the same protocol for creating your class
      # as Array then you'd need something like this.
      def initialize(*args, &block)
           @array = Array.new(*args, &block)
      end

      def self.[](*objs)
           new().replace(Array[*objs])
      end
=end

      def replace(other_array)
           self.array = other_array.to_ary  # use to_ary instead of to_a
      end

      # to_ary is used for internal conversions of objects
      def to_ary
           array
      end

      # For a method which was replaced in your subclass just replace
      # explicit (or implicit) self with @array
      def concat(other_arr)
            array.concat(other_arr.to_pairs)
      end

      def sort_by(&b)
            Pairs.new(@array.sort_by(&b))
      end

      def to_pairs
          self
      end

end

class Array
      def to_pairs
          Pairs.new(self)
      end
end



-- 
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/