【问题标题】:dynamically create a class without a namespace动态创建一个没有命名空间的类
【发布时间】:2009-12-22 09:39:48
【问题描述】:

我正在尝试使用 eval 方法动态创建一个类。除了一个小问题外,它工作正常。正如我的代码所示,我正在 BrowserFactory 类中创建 Browser 类。当我这样做时,Browser 类添加了 BrowserFactory 命名空间。是否可以在没有附加 BrowserFactory 命名空间的情况下从字符串评估 Browser 类?


class BrowserFactory
  def self.create_browser(browser)
    super_class = nil
    case browser
    when 'IE'
      require 'watir'
      super_class = 'Watir::IE'
    when 'celerity'
      require 'celerity'
      super_class = 'Celerity::Browser'
    end

    raise StandardError.new("Browser '#{browser}' is not currentlys supported") if super_class.nil?

    eval <<EOS
class Browser < #{super_class}
include Singleton
include BrowserModification
end
EOS

    return Browser.instance
  end

end

【问题讨论】:

    标签: ruby metaprogramming eval


    【解决方案1】:

    定义浏览器(或 ::Browser,直接回答您的问题)将阻止您多次致电您的工厂。

    我建议使用匿名类。不需要eval,顺便说一句,如果你愿意,你可以定义类方法to_s:

    class BrowserFactory
      def self.create_browser(browser)
        super_class = case browser
        when 'IE'
          require 'watir'
          Watir::IE
        when 'celerity'
          require 'celerity'
          Celerity::Browser
        else
          raise StandardError.new("Browser '#{browser}' is not currentlys supported")
        end
    
        klass = Class.new(super_class) do
          include Singleton
          include BrowserModification
          def self.to_s
            "Modified#{superclass}"
          end
        end
        klass.instance
      end
    end
    

    【讨论】:

    • 您实际上可以将设置块传递给Class.new,而不是单独调用class_eval
    • 确实,更好。谢谢:-)
    【解决方案2】:

    改变

    class Browser < #{super_class}
    

    class ::Browser < #{super_class}
    

    【讨论】:

      【解决方案3】:
      def BrowserFactory(browser)
        case browser
        when 'IE'
          require 'watir'
          Watir::IE
        when 'celerity'
          require 'celerity'
          Celerity::Browser
        else
          raise ArgumentError, "Browser '#{browser}' is not currently supported"
        end.new.extend(BrowserModification)
      end
      

      这是一个小测试套件:

      module Watir; class IE; def to_s; 'IE' end end end
      module Celerity; class Browser; def to_s; 'Celerity' end end end
      
      module BrowserModification; def to_s; "Modified#{super}" end end
      
      require 'test/unit'
      class TestBrowserFactory < Test::Unit::TestCase
        def test_that_celerity_responds_as_modified_celerity
          assert_equal 'ModifiedCelerity', BrowserFactory('celerity').to_s
        end
        def test_that_internet_explorer_responds_as_modified_internet_explorer
          assert_equal 'ModifiedIE', BrowserFactory('IE').to_s
        end
        def test_that_an_invalid_browser_raises_an_exception
          assert_raise ArgumentError do BrowserFactory('xyz') end
        end
      end
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-11-14
        • 2014-03-23
        • 2011-05-29
        • 2012-07-16
        • 1970-01-01
        • 2014-10-18
        相关资源
        最近更新 更多