Created
February 3, 2009 20:57
-
-
Save rosylilly/57747 to your computer and use it in GitHub Desktop.
Prototype class for ruby
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Object | |
def method_missing( _method, *arg) | |
_method = _method.to_sym | |
if (_method.to_s[_method.to_s.size - 1] == ?=) && ( arg[0].class == Proc) | |
target = (self.class == Class ? self : self.class) | |
target.class_eval do | |
define_method( _method.to_s[0, _method.to_s.size - 1].to_sym, arg[0].binding) | |
end | |
else | |
raise NoMethodError, "undefined method `#{_method}' for #{self.inspect}:#{self.class}", caller(1) | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Reference URL: | |
# http://d.hatena.ne.jp/javascripter/20081121/1227216175 | |
# http://d.hatena.ne.jp/keyesberry/20081022/p1 | |
# http://d.hatena.ne.jp/amachang/20061019/1161201903 | |
# http://blog.livedoor.jp/dankogai/archives/50663122.html | |
class Rototype | |
require 'forwardable' | |
include Enumerable | |
extend Forwardable | |
def initialize(obj = nil) | |
raise TypeError unless obj.class == Hash || obj.class == self.class || obj.nil? | |
@objects = {} | |
@objects[:__proto__] = nil | |
unless obj.nil? | |
(obj.to_hash || {}).each_pair do | key, val | | |
self[key] = val | |
end | |
end | |
end | |
# 別名宣言 | |
def this | |
self | |
end | |
def prototype | |
@objects[:__proto__] | |
end | |
def prototype=(obj) | |
raise TypeError if obj.class != self.class | |
@objects[:__proto__] = obj | |
end | |
def_delegator :@objects, :each, :each | |
def +(other) | |
raise TypeError if other.class != self.class && other.class != Hash | |
obj = self.class.new(other) | |
obj[:__proto__] = self | |
obj | |
end | |
def |(other) | |
obj = self.class.new() | |
obj[:__proto__] = self | |
other.each{|k, v| | |
unless key?(k) | |
obj[k] = v | |
end | |
} | |
obj | |
end | |
def new(obj = nil) | |
instance = self.class.new(obj) | |
instance[:__proto__] = self | |
return instance | |
end | |
def inheritance(obj = nil) | |
instance = self.class.new(obj) | |
instance[:__proto__] = self.class.new(self) | |
return instance | |
end | |
def merge!(obj) | |
@objects.merge!(obj || {}); nil | |
end | |
def merge(obj) | |
self.dup.merge!(obj) | |
end | |
def key?(data_name) | |
tmp = @objects.dup | |
begin | |
if tmp.key?(data_name.to_s.to_sym) | |
return true | |
end | |
tmp = tmp[:__proto__] | |
end until tmp.nil? | |
false | |
end | |
def [](data_name) | |
tmp = @objects.dup | |
begin | |
if tmp.key?(data_name.to_s.to_sym) | |
tmp = tmp[data_name.to_s.to_sym] | |
break | |
end | |
tmp = tmp[:__proto__] | |
end until tmp.nil? | |
tmp | |
end | |
def []=(data_name, data) | |
removeMethod(data_name.to_s.to_sym) | |
@objects[data_name.to_s.to_sym] = data | |
if data.class == Proc | |
addMethod(data_name.to_s.to_sym, data.binding) | |
end | |
end | |
def delete(name) | |
removeMethod(name.to_s.to_sym) | |
@objects.delete(name.to_s.to_sym) | |
end | |
def method_missing(method_name, *method_arg) | |
if self.key?(method_name.to_s.to_sym) | |
if respond_to?(method_name.to_s.to_sym) | |
method(method_name.to_s.to_sym, *method_arg) | |
else | |
if self[method_name.to_sym].class == Proc | |
addMethod(method_name.to_sym, self[method_name.to_sym].binding) | |
method(method_name.to_sym).call(*method_arg) | |
else | |
self[method_name.to_sym] | |
end | |
end | |
else | |
if method_name.to_s[method_name.to_s.size - 1].chr == '=' | |
self[method_name.to_s[0, method_name.to_s.size - 1].to_sym] = method_arg[0] | |
else | |
raise NoMethodError.new('undefined method `'+method_name.to_s+'`') | |
end | |
end | |
end | |
def to_hash | |
@objects | |
end | |
private | |
def addMethod(name,bind) | |
obj_singleton = class << self; self end | |
obj_singleton.class_eval do | |
define_method(name, bind) | |
end | |
end | |
def removeMethod(name) | |
obj_singleton = class << self; self end | |
obj_singleton.class_eval do | |
remove_method(name) if respond_to?(name) | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'prototype' | |
base = Rototype.new( :price => '$30', :quality => 'low'); # 安いが性能の低い物 | |
quality = base.new( :quality => 'high'); # 安くて性能が良い | |
low = base.inheritance( :price => '$30'); # 高くて性能が悪い | |
base.quality = 'better' # baseの性能は普通になった | |
base.price = '$100' # しかも値段も上がった | |
p quality.price # qualityの値段もあがった => $100 | |
p low.price # しかしlowは参考にしただけで技術を継承していないので値段もそのまま => $30 | |
p quality.quality # 性能はやっぱりよい => high | |
p low.quality # 上記の理由で継承してないから性能もそのまま => low |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment