2016-04-26 39 views
1

我在Ruby中編寫了一個編譯器,並且我有許多實例方法將修改實例變量的類。例如,我的詞法分析器(即在代碼中發現的標記部分),工作原理是這樣的:應該在Ruby中修改實例變量嗎?

class Lexer 
    attr_accessor :tokens 

    def initialize(input) 
    @input = input 
    @tokens = nil 
    end 

    def lex! 
    # lex through the input... 
    # @tokens << { lexeme: 'if', kind: :if_statement } 

    @tokens 
    end 
end 

lexer = Lexer.new('if this then that') 
lexer.lex! # => [ { lexeme: 'if', kind: :if_statement }, ... ] 
lexer.tokens # => [ { lexeme: 'if', kind: :if_statement }, ... ] 

這是一個有效的做法呢?或者,我是否應該使用方法(如#lex)接受輸入並返回結果,而不修改實例變量?

class Lexer 
    def initialize 
    end 

    def lex(input) 
    # lex through the input... 
    # tokens << { lexeme: 'if', kind: :if_statement } 

    tokens 
    end 
end 

lexer = Lexer.new 
lexer.lex('if this then that') # => [ { lexeme: 'if', kind: :if_statement }, ... ] 

回答

1

根據您的設計目標以及詞法分析器的使用方式,這兩種方法都是有效的。

你實際上需要一個包含令牌的實例變量嗎?例如,詞法分析器是否需要將它們用於其他任何事情?如果不是,我會傾向於不使用實例變量,並且你不需要推理(例如,「這個實例變量是否會被其他系統交互所改變」)。

+0

不,它不會用'@ tokens'做任何事情。我認爲這幾乎可以回答我的問題,謝謝! –

+0

@EthanTurkeltaub \t這是一種功能性與非功能性的方法,真的。 –

1

在一個實例的方法中改變一個實例變量是完全有效的(這就是爲什麼它們存在於第一位)。但是,某些數據片段是否應保存在實例變量中,取決於您的實例將如何使用。

你能想到的實例變量爲您的實例的狀態的,和你的情況爲你的實例變量狀態管理的。例如,如果您有Counter類,例如incrementdecrement方法,則計數器的當前值顯然是狀態的一部分,並且這些方法會改變它。

一個好的經驗法則是:是否會來回傳遞數據?如果你是,那麼它可能應該是一個實例變量。如果你不是,那麼它不是你的實例狀態的一部分,應該保持在它之外。你的情況:

lexer = Lexer.new 
tokens = lexer.lex('my statement') 
lexer.do_something_else tokens # if you do that, then lexer should be aware of the tokens and keep it in an instance variable, if not: why bother ? 

作爲結論,這一切都取決於Lexer是否是功能性的實用工具類,或者如果它的實例必須是有狀態的。