Ruby attr_accessor 问题探讨

HM · 2023年03月18日 · 最后由 haohaodehao 回复于 2023年03月29日 · 443 次阅读

一段简单的求斐波拉契数列的 ruby 代码,Fibnacci 类中 attr_accessor 方法定义的属性:memo, :index,代码如下


# 求斐波拉契数列的一个简单方法
class Fibnacci
  attr_accessor :memo, :index
  def initialize
    @memo = {}
    @index = 0
  end


  def fib_pro(n)
    return memo[n] if memo.has_key? n 
    return 1 if n <= 2
    memo[n] = fib_pro(n-1) + fib_pro(n-2) 
  end

  def next
    # index = @index + 1 # 错误用法1
    # index +=1                # 错误用法2
    @index += 1               # 正确用法
    fib_pro(index)
  end
end

obj = Fibnacci.new
puts obj.next
puts obj.next
puts obj.next
puts obj.next
puts obj.next
puts obj.next

期望输出

1
1
2
3
5
8

代码中错误用法 1 得不到正确结果,@index 值没有更新, 错误用法 2 直接报错:undefined method `+' for nil:NilClass (NoMethodError) 问题:为啥同是 attr_accessor 定义的属性 memo[n] = 可以正常使用,index += 报错,index = @index + 1 也不生效 工作中也发现有时候部分 attr_accessor 定义的属性赋值后没被更新,始终没找到根因,求论坛里各路大神指导

新手常见的错误。。index = xxx 中的 index 会被解释成局部变量赋值,要使用 accessor 生成的方法,应该用 self.index = xxxx

def next
  # 加一个self,避免index被识别为局部变量 
  self.index += 1

  # 或者这样,右边的index会被识别为 index()
  self.index = index + 1
  fib_pro(index)
end

这个原因在于,把index =中的index放到=左边时,会直接识别为局部变量,而不会识别为方法调用。这是 Ruby“不用声明变量即可使用”导致的结果。

attr_accessor 是给外部访问 Object 的内部 properties 用的,class 内的 method 使用直接用”@name/@name=“取值和赋值

需要 登录 后方可回复, 如果你还没有账号请 注册新账号