【问题标题】:Dynamic Inheritance in RubyRuby 中的动态继承
【发布时间】:2009-11-05 10:21:29
【问题描述】:

我正在尝试创建一个 Ruby 类,它的类型非常灵活,并希望可以根据其初始化的值从许多其他类继承属性:

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)

我知道 - 或者更确切地说已经阅读过 - mixin 的强大功能,但据我所知,这并不是完全正确的。有没有人有任何想法,或者我是否正在尝试其他方式最好的方法(例如,@content,其中包含etc 作为StringIOEnumerable 等)。

谢谢!

【问题讨论】:

    标签: ruby class inheritance


    【解决方案1】:
    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)
    

    【讨论】:

    • 当然,Test#initialize 逻辑意味着它可以被重写以接受一个字符串并根据它需要的任何规则确定所需的类——这就是计划!干杯!
    【解决方案2】:

    没有理由传递一个代表类名的字符串——你可以只传递一个类或类的实例。这是一个接受对象并打开其类型的版本。

    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)
    

    【讨论】:

    • 我实际上是在解析一个字节字符串来生成这些对象,所以我必须即时创建对象,但是这种方法的转发似乎很完美!只是一个想法,有没有一种简单的方法来转发所有方法,或者排除某些方法,而不是必须全部指定它们?
    • 没有必要明确列出所有这些。您可以轻松地将forwarded_methods 设置为@content.methods - Object.instance_methods - [some list of other methods to exclude]
    • 嗯,我收到一个错误:NoMethodError: undefined method ‘module_eval’ for #&lt;Test:0x10011e148 @content=[1, 2, 3]&gt; Test 是否必须从特殊类继承?
    • 哦,奇怪。实例可以在 Ruby 1.9 中扩展 Forwardable,但在 Ruby 1.8 中不能。在两者中都测试了这个新版本,它应该可以正常工作。
    【解决方案3】:

    检查DelegateClass和Forwardable,我认为这更多是你需要去的方向(通用外观容器)。你不需要为他们上课。因为类只是一个对象,而不是纯粹的句法结构。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-09
      • 2013-12-20
      • 2016-06-20
      • 2014-01-30
      • 1970-01-01
      相关资源
      最近更新 更多