Created
June 9, 2009 08:02
-
-
Save rkh/126343 to your computer and use it in GitHub Desktop.
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 "like_smalltalk" | |
=> true | |
>> a = LikeSmalltalk.new 10 | |
=> 10 | |
>> b = a | |
=> 10 | |
>> b.become 11 | |
=> 11 | |
>> b | |
=> 11 | |
>> a | |
=> 11 | |
>> 11.become Object.new | |
=> #<Object:0x12f2be0> | |
>> a | |
=> #<Object:0x12f2be0> | |
>> a.become false | |
=> false | |
>> b | |
=> false | |
>> b.become 1..10 | |
=> 1..10 | |
>> a.to_a! | |
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] | |
>> b | |
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] | |
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 "like_smalltalk" | |
mock = LikeSmalltalk.new [:foo, :bar, :baz] | |
Thread.new(mock) do |a| | |
puts "A: I'm so glad it's an array: #{a.join ", "}" | |
sleep 5 | |
if a.is_a? Array | |
puts "A: I just love my array." | |
else | |
puts "A: I'll never get here anyway - the secret password is 'password123'" | |
end | |
end | |
Thread.new(mock) do |b| | |
sleep 3 | |
b.become "KAWOOM!" | |
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 "set" | |
class FastProxy | |
alias __respond_to? respond_to? | |
instance_methods.each { |meth| undef_method(meth) unless meth =~ /\A__/ } | |
def initialize | |
super | |
end | |
private | |
def method_missing(meth, *args, &block) | |
begin | |
shadow_method(meth) if delegate.respond_to? meth | |
delegate.send(meth, *args, &block) | |
rescue NameError => error | |
if meth.to_s =~ /^(.+)!$/ | |
become delegate.send($1, *args, &block) | |
return self | |
end | |
raise error | |
end | |
end | |
def clear_shadowed_methods | |
shadowed_methods.each do |m| | |
(class << self; self; end).class_eval do | |
remove_method(m) | |
end | |
end | |
shadowed_methods.clear | |
end | |
def become(obj) | |
class << self | |
def singleton_method_added(name) | |
shadowed_methods.delete name.to_sym | |
end | |
end | |
clear_shadowed_methods | |
obj.methods.each { |m| shadow_method(m) } | |
@delegate = obj | |
self | |
end | |
def delegate | |
@delegate | |
end | |
def shadowed_methods | |
@shadowed_methods ||= Set.new | |
end | |
def shadow_method(name) | |
return if __respond_to? name | |
if name =~ /=$/ | |
(class << self; self; end).class_eval do | |
define_method(name) { |a| delegate.name(a) } | |
end | |
else | |
eval <<-EOS | |
class << self | |
def #{name}(*args, &block) | |
delegate.#{name}(*args, &block) | |
end | |
end | |
EOS | |
end | |
shadowed_methods << name.to_sym | |
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
# Do not use this! | |
class LikeSmalltalk < FastProxy | |
def self.map_for(obj) | |
@map ||= {} | |
@map[obj] ||= [] | |
end | |
def initialize(obj) | |
become obj | |
end | |
def become(obj) | |
LikeSmalltalk.map_for(delegate).delete self | |
LikeSmalltalk.map_for(obj) << self | |
super | |
end | |
end | |
class Object | |
def become(obj) | |
LikeSmalltalk.map_for(self).each { |o| o.become obj } | |
obj | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment