インスタンスが属するクラスをあとから変更する操作を Ruby で
Ruby では evil-ruby の #class= が必要になります。また、Ruby には Smalltalk の #become: に相当する機能もないので、Python で使った transmogrify もどき(実装は泥くさいものとなってしまいましたが…^^;)を新たに作り、Smalltalk の #as: っぽい振る舞いとの合わせ技で実現してみました。
require 'rubygems' require 'evil' class Object; def as(similar_class); similar_class.new_from(self) end end class Cartesian attr_reader :x, :y def initialize(x, y) @x = x @y = y end def self.new_from(polar) self.new(polar.r * Math.cos(polar.theta), polar.r * Math.sin(polar.theta)) end end class Polar attr_reader :r, :theta def initialize(r, theta) @r = r @theta = theta end def self.new_from(cart) self.new(Math.sqrt(cart.x**2 + cart.y**2), Math.atan2(cart.y, cart.x)) end end def transmogrify(a, b) a.class = b.class a.instance_variables.each{ |v_name| a.instance_eval{ remove_instance_variable(v_name) } } b.instance_variables.each{ |v_name| val = b.instance_eval{ instance_variable_get(v_name) } a.instance_eval{ instance_variable_set(v_name, val) }} a end pos1 = pos2 = Polar.new(Math.sqrt(2), Math::PI/4) pos1.class #=> Polar transmogrify(pos1, pos1.as(Cartesian)) pos1.class #=> Cartesian pos1.x #=> 1.0 pos1.y #=> 1.0 pos2.class #=> Cartesian transmogrify(pos1, pos1.as(Polar)) pos1.class #=> Polar pos1.r #=> 1.4142135623731 pos1.theta / Math::PI #=> 0.25