2013-11-20 113 views
0

的方面,我有以下代碼評估和演示在另一類

class Tester 

    def eval_something(string) 
    eval(string) # How to change? 
    end 

    def printer 
    p "Not what I want" 
    end 
end 

class MyClass 

    def printer 
    p "Hello World" 
    end 
end 

t = Tester.new 
t.eval_something("printer") 

我想要一個Tester實例的eval_something到的MyClass背景下評估的代碼。因此,例如,我希望此腳本打印出Hello World而不是Not what I want

這可以實現嗎?

+0

你不希望MyClass作爲測試器的子類..對嗎?或者您準備好同意更改您的代碼的任何建議? –

+0

是的,'MyClass'是一個獨立的實體,與'Tester'無關。基本上我想知道我是否可以讓一個類使用另一個類的上下文進行評估。 – MxyL

+0

你的問題沒有意義。 'printer'是一個實例方法。它不能在「MyClass」上下文中評估 - 只能在「MyClass」的_instance_上下文中進行評估。針對您的問題有各種可能的解決方案,但它們都涉及代碼結構的根本性改變,而且我不清楚您實際需要什麼。 這聽起來像你想調用另一個類的實例方法而不創建該類的實例,但這沒有任何意義。 – Max

回答

0

不太清楚這是否會工作,你的目的,但你可以試試這個:

class Tester 
    def eval_something(string) 
    MyClass.send(string.to_sym) # Send will evaluate the symbol passed to it. Equivalent of calling MyClass.printer in this case 
    end 

    def printer 
    p "Not what I want" 
    end 
end 

class MyClass 
    def self.printer # This needs to be a class method since MyClass does not inherit from Tester in this example 
    p "Hello World" 
    end 
end 

t = Tester.new 
t.eval_something("printer") 

=> "Hello World" 
+0

我想我可以像@tlewin建議的那樣實例化MyClass的一個實例並將其發送給它。另一方面,如果我要實例化一個,我可以實例化一次,將它作爲一個類變量存儲,然後用它來代替。 – MxyL

0

在你的榜樣,您可以使用instance_eval方法並傳遞一個MyClass參考:

t = Tester.new 
t.instance_eval do 
    MyClass.new.printer 
end 

這將返回「Hello World」。

instance_eval運行您在對象上下文中傳遞的代碼塊。在這種情況下,您可以訪問任何實例變量。例如:

class Test 
    def initialize any 
    @any = any 
    end 
end 

t = Test.new('abc') 
t.instance_eval {puts @any} 

它將打印'abc'。

建議使用instance_evalclass_eval方法,因爲它使您可以更好地控制執行的內容。這是一個更安全的選擇。

eval方法可以執行任意代碼。如果你不控制字符串的內容,這將是非常危險的選擇。

+0

您對'instance_eval'的使用完全與該問題相切。在'Tester'的實例上使用它並不會讓調用'MyClass'的實例方法變得更容易。 – Max

+0

@Max你完全正確。這就是我在'instance_eval'代碼塊中包含'MyClass.new'的原因。 –