Раздел «Язык Ruby».RubySchoolSourceL08:
<<Программирование на Ruby

Занятие 8: ООП на примере класса Set

Следующее занятие
Предыдущее занятие

Простой код

class Set 
  def initialize(*elements)
    @hash = elements.inject({}) {|h,e| h[e] = true; h}
  end
  
  def to_a
    @hash.keys
  end
  
  # iterate all elements
  def each(&block)
    @hash.each_key(&block)
  end
  
  # Inserts element to set.
  # Returns true if element is inserted.
  # Otherwise returns false.
  def insert(x)
    @hash[x] = true
  end

  def empty?
    @hash.empty?
  end

  def include?(x)
    @hash.include?(x)
  end

  def size
    @hash.size
  end
  
  def inspect
    "Set {#{to_a.join(',')}}"
  end
  
  include Enumerable
end

Код c delegate

def extract_options(ary)
  (Hash === ary.last) ? ary.pop : {}
end

class Module
  # delegation
  def delegate(*methods)
    options = extract_options(methods)
    to = options[:to] or raise ArgumentError, "option :to must be specified"
    
    methods.each do |method|
      define_method(method) do |*args|
        send(to).send(method, *args)
      end
    end
  end
end

class Set 
  def initialize(*elements)
    @hash = elements.inject({}) {|h,e| h[e] = true; h}
  end
  
  def to_a
    @hash.keys
  end
  
  # iterate all elements
  def each(&block)
    @hash.each_key(&block)
  end
  
  # Inserts element to set.
  # Returns true if element is inserted.
  # Otherwise returns false.
  def insert(x)
    if @hash.has_key?(x)
      false
    else
      @hash[x] = true
    end
  end
  alias << insert
  
  delegate :include?, 
    :empty?, 
    :delete, 
    :size,
    :to => :hash
  
  def join!(s)
    @hash.merge!(s.hash)
  end
  
  def inspect
    "Set {#{to_a.join(',')}}"
  end
  
  protected
  def hash
    @hash
  end
  
  
  class <<self
    def [](*ary)
      Set.new(*ary)
    end
  end
  
  include Enumerable
end

s = Set[111,434,56,1,2,3,4]

puts s.inspect
puts s.sort.inspect
puts s.map{|a| a**2}.inspect

s1 = Set.new

s1 << 1
s1 << 6
s1 << 1
s1 << 2

puts s1.size
puts s1.include?(23)

s2 = Set.new(5, 55, 2)

s1.join!(s2)

puts s1.to_a.inspect