From: jweirich@... Date: 2001-08-20T06:15:27+09:00 Subject: [ruby-talk:19993] pose_as I was reading someone commenting about Objective C yesterday. They said that Objective C was able to do [NewClass poseAs: [OldClass class]]; (note Smalltalk like syntax). Thereafter any time [OldClass new] was executed, an object of class NewClass would be created instead. This sounded like a useful thing to have when doing testing (e.g. replacing the construction of a real object with a testable Mock version), so I wondered if the same could be done in Ruby. Here's the result ... ---------------------------------------------------------------------- class Class def pose_as(other_class) if other_class.methods.include?("_unposed_new_") fail "Another class is already posing as #{other_class.name}" end other_class.class_eval <<-EOS class << self alias _unposed_new_ new @@use_original = false def new(*args) if @@use_original _unposed_new_(*args) else @@use_original = true result = #{name}.new(*args) @@use_original = false result end end end EOS end def unpose if not self.methods.include?("_unposed_new_") fail "No class is posing as #{self.name}" end self.class_eval <<-EOS class << self alias new _unposed_new_ remove_method :_unposed_new_ end EOS end end ---------------------------------------------------------------------- Load the code and then saying MockThing.pose_as(Thing) will cause all evaluations of Thing.new to return a MockThing.new object instead. Say: Thing.unpose to undo the effect. A couple of limitations ... o MockThing must have a compatible version of initialize(). o Only one level of posing is allowed, exception otherwise. o The posing code is not thread safe (we use a class variable flag ... elegant solutions to this limitation is cheerfully solicited). I'm not suggesting this as a standard part of Ruby, but I do think it is a tribute to the flexibility of the language to allow expressing this kind of stuff within the language. -- -- Jim Weirich jweirich@one.net http://w3.one.net/~jweirich --------------------------------------------------------------------- "Beware of bugs in the above code; I have only proved it correct, not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)