class Prototype
  def initialize
    @_method_list = {}
  end

  def _my_eval(*_str, &block)
    _s = (class << self; self; end)
    if block_given?
      _s.module_eval &block
    else
      _s.module_eval _str[0]
    end
  end

  def method_missing( _name, *_args)
    if _name.to_s =~ /([^=]+)=/ # 代入?
      _name_ = $1
      _my_eval %-
        def #{_name_}() @#{_name_} end
        def #{_name_}=(_val)
          if _val.kind_of? Proc
            @_method_list[ "#{_name_}" ] = _val
            _my_eval { define_method( :#{_name_}, _val) }
          else
            if @_method_list[ "#{_name_}" ]
              @_method_list[ "#{_name_}" ] = nil
              _my_eval { define_method( :#{_name_}) { @#{_name_}} }
            end
            @#{_name_} = _val
          end
        end
      -
      _x = _args
      _x = _args[0] if _x.kind_of? Array and _args.size==1
      send( _name, _x)  # _name_ = *_args
    else
      p "method_missing: #{_name.to_s}, #{_args}" if $DEBUG
      nil
    end
  end

  def get_method _name
    @_method_list[ _name ]
  end
end
a = Prototype.new

p a.x # => nil
a.x = 99
p a.x # => 99
a.x = "foo"
p a.x # => "foo"

p "---"
b = a.dup
b.y = "bar"
y = "global y"
b.x = lambda() { self.y }
   # selfがないと上のyを参照してしまう
p b.x # => "bar"
p a.x # => "foo"

p "---"
a.y = "buz"
a.x = b.get_method("x")
p a.x # => "buz"

javascriptのソースを移植するために作ってみたんだけれど,javascriptってこんな感じなの?


追記:dupじゃなくてcloneにしないと特異メソッドがコピーされない.なるほど.