方法应该修改Ruby中的实例变量吗?

时间:2016-04-26 18:53:57

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

2 个答案:

答案 0 :(得分:1)

根据您的设计目标和词法分析器的使用方式,两者都有效。

你真的需要包含令牌的实例变量吗?例如,词法分析者是否需要将它们用于其他任何事情?

如果没有,我倾向于不使用实例变量,并且你没有理由(例如,“这个实例变量会被其他系统交互改变”)。

答案 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是否是一个功能实用程序类,或者它的实例是否需要是有状态的。