2009-12-22 61 views
1

我想動態地使用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 

回答

3

定義瀏覽器(或瀏覽器::,直接回答你的問題)會阻止你打電話給你的工廠不止一次。

我會推薦使用匿名類。

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 
+1

實際上,你可以只通過安裝塊無需EVAL,順便說一句,你可以,如果你要定義的類方法to_s 'Class.new',而不是單獨調用'class_eval'。 – Chuck 2009-12-22 16:06:55

+0

確實,更好。謝謝 :-) – 2009-12-22 16:27:49

2

變化

class Browser < #{super_class} 

class ::Browser < #{super_class} 
0
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