Dynamic Inheritance in Ruby
I'm trying to make a Ruby class that is very flexible as to it开发者_运维问答s type and hopefully can inherit properties from a number of other classes depending on the values its initialized with:
class Test
def initialize(type,etc)
case type
when "stringio"
inherit_from_stringio_with_data(etc)
when "list"
inherit_from_enumerable_with_data(etc)
# and so on
end
end
end
Test.new("list").each do |item|
p item
end
s = Test.new("stringio")
s.seek(3)
puts s.read(2)
I know of - or rather have read of - the power of the mixin, but as far as I can tell this isn't quite laid out correctly. Does anyone have any ideas, or am I trying something that's best achieved otherways (by having, say @content
, that contains etc
as a StringIO
, Enumerable
etc).
Thanks!
module Stringy
def foo
puts "I am a stringy"
end
end
module Inty
def bar
puts "I am inty"
end
end
class Test
def initialize(mod_type)
self.extend(mod_type)
end
end
test = Test.new(Stringy)
There's no reason to pass a string representing a class name — you can just pass a class or instance of a class. Here's a version that takes an object and switches on its type.
class Test
def initialize(obj)
@content = obj
forwarded_methods = case @content
when StringIO then [:seek, :read]
when Enumerable then [:each]
else raise "Invalid type"
end
eigenclass = class<<self; self; end
eigenclass.class_eval do
extend Forwardable
def_delegators :@content, *forwarded_methods
end
end
end
Test.new([1,2,3]).each do |item|
p item
end
s = Test.new(some_stringio_object)
s.seek(3)
puts s.read(2)
Check DelegateClass and Forwardable, I think this is more the direction you need to go (universal facade containers). You don't need to have classes for them per s.e. since a class is just an object and not purely a syntactic construct.
精彩评论