DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

Alternative To Inheriting From Array

09.09.2006
| 4047 views |
  • submit to reddit
        Taken from: 

http://rubylution.ping.de/articles/2005/12/21/rubys-rich-array-api/

Author: Florian Frank



class Class
  def extract(included, inherit_from = [ Object ])
    included = included.map { |m| m.to_s }
    inherited = inherit_from.inject([]) do |i, modul|
      i.concat modul.instance_methods
    end
    klass = dup
    klass.instance_eval do
      instance_methods.each do |m|
        unless included.member? m or inherited.member? m
          undef_method m
        end
      end
    end
    klass
  end

  def rename(names = {})
    names.each do |old_name, new_name|
      instance_eval do
        alias_method new_name, old_name
        undef_method old_name
      end
    end
    self
  end

  def alias(names = {})
    names.each do |old_name, new_name|
      instance_eval do
        alias_method new_name, old_name
      end
    end
    self
  end

  def define(*args, &block)
    define_method(*args, &block)
    self
  end
end




Stack = Array.extract([
  :last,
  :push,
  :pop,
  :size,
  :clear,
  :inspect,
  :to_s
])

if $0 == __FILE__
  s = Stack.new
  s.push 1
  s.push 2
  s.push 3
  puts s.inspect       # => [1, 2, 3]
  s.last  # => 3
  s.pop   # => 3
  puts s.inspect       # => [1, 2]
end

Queue = Array.extract([
  :first,
  :push,
  :shift,
  :clear,
  :size,
  :inspect,
  :to_s
]).rename(
  :push   =>  :enqueue,
  :shift  =>  :dequeue
)

if $0 == __FILE__
  q = Queue.new
  q.enqueue 1
  q.enqueue 2
  q.enqueue 3
  puts q.inspect         # => [1, 2, 3]
  q.first   # => 1
  q.dequeue # => 1
  puts q.inspect         # => [2, 3]
end

List = Array.extract([
  :first,
  :last,
  :push,
  :insert,
  :delete,
  :delete_at,
  :[],
  :[]=,
  :size,
  :each,
  :length,
  :inspect,
  :to_s
], [ Object, Enumerable ]).rename(
  :push   =>  :add
).alias(
  :[]     =>  :get,
  :[]=    =>  :put
).define(:sum) { |*start|
  inject(start[0] || 0) { |s,x| s + x }
}

if $0 == __FILE__
  l = List.new
  l.add 1
  l.add 2
  l.add 3
  puts l.inspect             # => [1, 2, 3]
  l.delete 2    # => 2
  puts l.inspect            # => [1, 3]
  l.add 2
  puts l.inspect             # => [1, 3, 2]
  l.delete_at 1 # => 3
  puts l.inspect             # => [1, 2]
  l.get 0       # => 1
  l.put 0, 23   # => 23
  puts l.inspect             # => [23, 2]
  l.sum         # => 25
  m = List.new
  m.add "foo"
  m.add "bar"
  m.sum ""      # => "foobar"
end