Sean O'Halpin
2/28/2009 10:36:00 PM
On Sat, Feb 28, 2009 at 8:50 PM, Ian Trudel <ian.trudel@gmail.com> wrote:
[snip]
> We should perhaps see the problem as if it was extreme: let's imagine
> that we have multiple programs which have each a class Data but is
> completely different (no similar instance variables nor methods, nothing
> in common at all). No access to those programs and yet have to load all
> the files within a single Ruby program. What one would do?
Well, you could dynamically extend the loaded instances with modules
that add the specific required behaviour.
Something like this:
First file represents whatever created the data in the first place:
# file1
class MyData
attr_accessor :kind
attr_accessor :name
def initialize(kind, name)
@kind = kind
@name = name
end
end
instance = MyData.new("Greeting", "World")
data = Marshal.dump(instance)
File.open("data.dat", "wb") do |file|
file.write(data)
end
# end of file1
Second file shows how you could load this data and dynamically decide
how it should behave as an instance:
# file2
# these modules will be used to extend the loaded instance depending
# on its @kind
module Hello
def run
puts "Hello #{ @name }"
end
end
module Goodbye
def run
puts "Goodbye #{ @name }"
end
end
# You need to define this if you're unmarshalling data that has been
# saved as MyData - no way round it as Marshal embeds the class name
# in the data
class MyData
end
# unmarshall data and extend depending on the @kind
data = File.read("data.dat")
instance = Marshal.load(data)
# this is shorthand for determining the nature of the data
if instance.instance_variable_defined?("@kind")
kind = instance.instance_variable_get("@kind")
if Object.const_defined?(kind)
extension = Object.const_get(kind)
instance.extend(extension)
instance.run
else
puts "@kind not known: #{instance.inspect}"
end
else
puts "@kind not defined for: #{instance.inspect}"
end
# end of file2
I'm using @kind as shorthand to stand for something that distinguishes
between instances of your data. (BTW, you can't use Data as a class
name in Ruby - it's reserved for use with C extensions).
HTH,
Regards,
Sean