2016-04-26 32 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

いいえ、@トークンでは何もしません。私はかなり多くの私の質問に答えると思う、ありがとう! –

+0

@EthanTurkeltaub \tこれは機能と非機能のアプローチのようなものです。 –

1

あなたのインスタンスのメソッドの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が機能ユーティリティクラスがあるかどうかによって決まります。

関連する問題