Skip to content

Instantly share code, notes, and snippets.

@pasberth
Created August 26, 2011 14:01
Show Gist options
  • Select an option

  • Save pasberth/1173459 to your computer and use it in GitHub Desktop.

Select an option

Save pasberth/1173459 to your computer and use it in GitHub Desktop.
Class を使わないでオブジェクト指向っぽいことをする
module Kernel
def object &definition
# binding
attrs = {}
# object
obj = proc { |attr_name|
{ :self => obj,
:dict => function(obj) { |this| this.dict },
:set => function(obj) { |this, attr_name, value| this.dict[attr_name.to_sym] = value },
:get => function(obj) { |this, attr_name| this.dict[attr_name.to_sym] },
:define => function(obj) { |this, func_name, &func| this.dict[func_name.to_sym] = function(this, &func) }
}.each do |k, v|
next if attrs.key? k
attrs[k] = v
end
attrs[attr_name.to_sym]
}
obj.instance_eval {
@value = self
@attrs = attrs
def value; @value; end
def dict; @attrs; end
def method_missing attr_name, *args
attr = call(attr_name.to_sym)
return nil unless attr
attr.value
end
}
obj.instance_eval &definition
obj
end
def string str
object {
@str = str
def to_s
@str
end
}
end
def function this, &proc
object {
@proc = proc
@this = this
def apply this, *args, &blk
@proc.call this, *args, &blk
end
def [] *args, &blk
@proc.call @this, *args, &blk
end
}
end
end
if __FILE__ == $PROGRAM_NAME
require "test/unit"
class TestBlsObjects < Test::Unit::TestCase
def setup
end
def test_set
obj = object {}
obj.set[:hello, string("hello")]
assert_equal obj.hello.to_s, "hello"
assert_equal obj.get[:hello].to_s, "hello"
end
def test_define
obj = object {}
obj.define[:hello, &proc { |this, your_name|
string "hello #{your_name}."
}]
assert_equal obj.hello['pasberth'].to_s, 'hello pasberth.'
end
def test_apply
obj1 = object {}
obj2 = object {}
obj1.set[:hello, string("hello")]
assert_equal obj2.get.apply(obj1, :hello).to_s, "hello"
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment