2009-06-11 56 views
5

我有一個好奇心的問題。如果我有一個ruby類,然後在執行過程中動態添加類方法,類變量等,那麼對於我來說保存已更改的類定義,以便下次啓動我的應用程序時,我可以再次使用它?保存動態Ruby類

回答

1

簡單地編組對象(正如別人所說)不會工作。讓我們看一個例子。考慮這個類:

class Extras 
    attr_accessor :contents 
    def test 
    puts "This instance of Extras is OK. Contents is: " + @contents.to_s 
    end 

    def add_method(name) 
    self.class.send :define_method, name.to_sym do 
     puts "Called " + name.to_s 
    end 
    end 
end 

現在,讓我們寫一個程序,它創建一個實例,增加了一個方法,並將其保存到磁盤:

require 'extras' 

fresh = Extras.new 
fresh.contents = 314 
fresh.test # outputs "This instance of Extras is OK. Contents is: 314" 
fresh.add_method(:foo) 
fresh.foo # outputs "Called foo" 

serial = Marshal.dump(fresh) 
file = File.new "dumpedExample", 'w' 
file.write serial 

所以我們可以正常調用方法「測試」和動態方法'foo'。讓我們看一下,如果我們寫一個加載其保存到磁盤實例的實例的程序會發生什麼:

require 'extras' 

file = File.new 'dumpedExample', 'r' 
serial = file.read 

reheated = Marshal.load(serial) 
reheated.test # outputs "This instance of Extras is OK. Contents is 314" 
reheated.foo # throws a NoMethodError exception 

所以我們可以看到,雖然實例(包括成員變量的值)保存的動態方法不是。

從設計角度來看,將所有添加的代碼放入模塊並在下次運行該程序時再次將其加載到類中可能會更好。我們需要一個很好的例子來說明如何才能真正瞭解這一點。

如果您需要額外的信息來重新創建方法,然後讓模塊將這些保存爲成員變量。在模塊中實現included,並讓它在包含到類中時查找這些成員變量。

-1

你正在編輯課程,你想保存它嗎?您可以嘗試使用Marshal模塊,它可以讓您將對象保存到文件中,並動態地將它們讀回內存。

4

沒有內置的方法來做到這一點。元帥不能保存方法。如果這些方法和變量是以某種系統的方式生成的,則可以保存該類所需的數據以重新創建它們。例如,如果您有定義這些方法的make_special_method(purpose, value)方法,請創建一個需要傳遞給這些方法的參數數組,並在您想重新構建類的狀態時讀取它。

2

根據你的意思,有幾種方法可以解決這個問題。

最簡單的情況是一個在那裏你已經添加變量或方法已經存在的類,如下面的例子:

class String 
    def rot13 
    return self.tr('a-z', 'n-za-m') 
    end 
end 

在這裏,我們已經添加了ROT13方法String類。只要運行此代碼,程序中的每個字符串都可以#rot13。因此,如果您的某些代碼需要具有rot13功能的字符串,則只需確保上述代碼在相關代碼之前運行,例如通過將rot13代碼放置在某個文件的某個位置並需要()它。好簡單!

但是,也許你已經添加了一個類變量的一類,並且要保留不只是它的存在,但它的價值,如:

class String 
    @@number_of_tr_calls_made = 0 
    # Fix up #tr so that it increments @@number_of_tr_calls_made 
end 

現在,如果你想保存的價值@ @number_of_tr_calls_made,你可以像使用任何其他可串行化的Ruby值一樣進行:通過Marshal庫。也很簡單!

但東西你措辭你的問題的方式令我懷疑你正在做這樣的事情:

greeting = "Hello" 
class <<greeting 
    def rot13 
    return self.tr('a-z', 'n-za-m') 
    end 
end 
encrypted_greeting = greeting.rot13 

這是我們在第一個例子做了很大的不同。這段代碼給你的程序中的每個字符串賦予rot13本身的權力。此代碼只將權限賦予名稱「greeting」引用的對象。在內部,Ruby通過創建String的匿名Singleton子類,將rot13方法添加到它以及將問候類更改爲該匿名子類來實現此目的。

這裏的問題是單身人士不能被編組(看看爲什麼,當任何對Marshal.load的調用可以生成現存的單身人士對象的副本時,如何保持Singleton不變量)。現在,問候在其繼承層次結構中有一個Singleton,所以如果你想保存並加載它,你就會被洗掉。請改爲創建子類:

class HighlySecurableString < String 
    def rot13 
    return self.tr('a-z', 'n-za-m') 
    end 
end 
greeting = HighlySecurableString.new("hello") 
+0

我認爲提問者是指在執行過程中添加到類中的方法。即元編程方法。我可能誤解了。 – toholio 2009-06-12 00:49:12