2016-04-26 6 views
1

Ich schreibe einen Compiler in Ruby, und ich habe viele Klassen, in denen Instanzmethoden Instanzvariablen ändern. Zum Beispiel mein Lexer (der Teil, der Token in dem Code findet), funktioniert wie folgt:Sollen Methoden Instanzvariablen in Ruby modifizieren?

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 }, ... ] 

Ist dies eine gültige Praxis? Oder sollte ich einen Ansatz verwenden, bei dem die Methoden (wie #lex) die Eingabe übernehmen und die Ergebnisse zurückgeben, ohne die Instanzvariablen zu ändern?

Antwort

1

Entweder ist gültig abhängig von Ihren Entwurfszielen und wie der Lexer verwendet wird.

Haben Sie eigentlich benötigen eine Instanzvariable, die die Tokens enthält? Z. B., muss der Lexer sie für irgendetwas anderes verwenden?

Wenn nicht, würde ich mich darauf konzentrieren, keine Instanzvariable zu verwenden, und Sie haben weniger zu verstehen ("wird diese Instanzvariable beispielsweise durch andere Systeminteraktionen geändert").

+0

Nein, es tut nichts anderes mit '@ Token'. Ich denke, dass so ziemlich meine Frage beantwortet, danke! –

+0

@EthanTurkeltaub \t Es ist eine Art der funktionalen gegenüber nicht-funktionalen Ansatz, wirklich. –

1

Es ist auf jeden Fall gültig, eine Instanzvariable in einer der Methoden Ihrer Instanz zu mutieren (deshalb existieren sie an erster Stelle). Ob ein Teil der Daten in einer Instanzvariablen gespeichert werden soll oder nicht, hängt jedoch davon ab, wie Ihre Instanz verwendet werden soll.

können Sie denken an Instanzvariablen als Zustand Ihrer Instanz und Ihrer Instanz als Zustand Manager für Ihre Instanzvariablen. Wenn Sie eine Counter Klasse haben, zum Beispiel mit increment und decrement Methoden, würde der aktuelle Wert Ihres Zählers eindeutig ein Stück des Staates sein, und diese Methoden würden es mutieren.

Eine gute Faustregel ist: Daten werden hin und her weitergeleitet? Wenn dies der Fall ist, sollte es wahrscheinlich eine Instanzvariable sein. Wenn dies nicht der Fall ist, ist es nicht wirklich Teil des Zustands Ihrer Instanz und sollte außerhalb dieser Instanz gehalten werden. In Ihrem Fall:

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 ? 

Als Schlussfolgerung, es hängt alles davon, ob Lexer ist eine funktionelle Utility-Klasse oder wenn seine Instanzen Stateful sein müssen.

Verwandte Themen