2009-11-10 53 views
1

我從遊戲的文本日誌,(例如)兩種類型的條目即。聊天和事件。在大多數情況下,它們非常相似,所以我有一個LogEntry類定義如此;self = Ruby中的後代?

class LogEntry < Array 
    def initialize(str) 
    super str.split 
    end 

    def parse 
    LogEntry.parse self 
    end 

    def LogEntry.parse(entry) 
    # Processes the elements that are in any Entry 
    # Figure out whether it's a Chat entry or an Event entry 
    # Returns an object of type LogChat or LogEvent 
    end 
end 

LogChat和LogEvent都會擴展LogEntry並進一步處理與其域相關的進一步處理。一切都按預期工作;

chat = LogEntry.new("some chat") 
event = LogEntry.new("some event") 

chat.parse.class # => LogChat 
event.parse.class # => LogEvent 

問: 類方法本質上LogEntry.parse返回合適類的解析條目。在這種情況下,解析的條目是重要的一點。但是,我們可以在實例方法「解析」重命名爲「what_type_should_i_be?」。我想讓物體作用於信息和「self.become LogEntry.parse(個體經營)」

眼下,解析條目,我必須這樣做;

entry = entry.parse 

我想進一步推動這一點,以便我得到相同的結果;

entry.parse 

我已經嘗試了明顯;

class LogEntry 
    def parse 
    self = LogEntry.parse(self) 
    end 
end 

但是,我收到錯誤Can't change the value of self。有誰知道我應該如何去實現這一目標?

編輯: 我改變了我的例子,因爲許多答案都關注於許多條目的迭代。查克的回答優雅地表明,這種情況不是問題。

如果這引起任何人的興趣,我已經絆倒了Evil Ruby這讓你干涉`self.class'。有一個很好的Orielly一篇關於它叫做Ruby code that will swallow your soul!我尋找到它,看它是否提供任何答案。 (編輯:evil.rb是有名的!低級別似乎不適合穩定/長期分佈的東西。)

回答

2

我認爲根本問題是each這裏是錯誤的方法。要麼parse更改對象的內部狀態而不是對象本身,或者使用map!用新版本替換集合中的對象。

entries.map! {|entry| entry.parse} 

將更新呼籲他們parse的結果數組中的對象,所以沒有理由這樣做怪異的東西selfparse方法。

+0

+1開始一個有趣的思路。我會看看我是否可以在'parse'方法中實現這個。我想讓對象看看自己並說「實際上,我正在使用這些類型的對象。」 – deau 2009-11-10 18:18:42

+0

你認爲我自己在做些奇怪的事嗎?從理論上講,以這種方式控制自己的對象是危險的嗎? – deau 2009-11-10 20:26:27

+1

那麼,在技術上不可能設置「自我」而沒有真正的低級別攻擊,這就是我的意思是「對自己做些奇怪的事情」。一個對象不能改變自己的身份(即使你可以在方法中設置self,它不會改變方法外的對象身份 - 變量只是引用)。一個對象只能控制其內部狀態,這就是爲什麼我建議代表可以改變這種方式的東西。 – Chuck 2009-11-10 20:53:23

0

對於初學者,您的意見說LogEntry.parse返回LogChat或LogEvent對象。所以你要求對象將自己改變爲不同類型的對象。

它也像類方法和實例方法被弄得有點 我猜一點,但爲什麼不能這樣做:

entries.each do |entry| 
    some_type_log = entry.parse 
    some_type_of_log.save! 
end 

編輯: 遺憾,想澄清一些東西。既然你正在分析數據是LogEntry的一部分,你想一個條目來解析本身,也沒有必要在任何參數來傳遞。只需保持parse方法無參數。

如果你知道是什麼類型的日誌東西,你可以跳過某個步驟,解析它的方式 chat_entry = LogChat.new。(:登錄=> LogEntry)

然後做一個方法叫做日誌這是你的解析器,明確處理聊天相關的項目。

+0

感謝您的時間m8,但我不會混淆實例/類方法;類方法LogEntry.parse導致逐漸更具體的EntryType.parse方法級聯。結果是一個完全解析和分類(按類)條目對象。實例方法解析調用LogEntry中的類方法,觸發一個新的級聯,以便您可以重新計算已經解析的條目。你的解決方案很好,與我已有的相似(請參閱問題!) – deau 2009-11-10 17:59:25

0

你有一些字符串/數組/ LogEntry混亂這裏,但假設你得到的制定,並在你還是希望有Array子類取代其網頁內容的最後,你需要使用replace

self.replace(LogEntry.parse(self)) 
+0

可悲的替換隻會複製數組的內容。 LogEntry的子類有實例變量(和一類課程!),它們不在替換範圍內。 – deau 2009-11-10 18:06:24

2

如果你可以打出來的功能分成不同的模塊,可以 變異 extend()self,只要你喜歡:

class LogEntry 
    ... 
    def parse!  # This mutates self! 
    case LogEntry.parse! 
    when :chat 
     self.extend MyApp::LogChat 
    when :event 
     self.extend MyApp::LogEvent 
    else 
     raise MyApp::Exception, "waaah" 
    end 
    end 
end 

你不必做一個笨重case語句重複調用self.extend(),當然,但你明白了。

+0

非常正確。我可以通過使用'self。@ type'而不是'self.class'來模擬整個事情。 Mixins可以添加相關的功能和實例變量。儘管如此,我還需要考慮一下。 – deau 2009-11-10 21:04:49

相關問題