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
On May 16, 2007, at 1:49 PM, Dan Z. wrote:
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:
alias_method :sort_by_old, :sort_by
PROBLEM here:
def sort_by(&block)
ary = self.sort_by_old {yield(block)}
Pairs.new(ary)
end
Use this instead:
ary = self.sort_by_old(&block)
p=Pairs[“abcd”, “efg”, “hi”, “j”]
=> [“abcd”, “efg”, “hi”, “j”]
p.class
=> Pairs
q=p.sort_by{|x| x.length}
=> [“j”, “hi”, “efg”, “abcd”]
q.class
=> Pairs
-Mark
Thanks, that worked immediately.
Dan
@array = array
end
def to_pairs
Thanks for the code examples–I previously didn’t understand exactly how
delegation worked. This looks neat. I’ll be playing with this and will
most likely use it.
Thanks again,
Dan
On 5/16/07, Dan Z. [email protected] wrote:
self.replace(ary)
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/