Ruby 【疑惑】关于局部变量与实例属性名称相同时,方法调用报错

3014zhangshuo · 2021年05月19日 · 最后由 3014zhangshuo 回复于 2021年05月20日 · 370 次阅读
class A
  attr_reader :content

  def initialize(content)
    @content = content
  end

  def hi
    content = content.gsub("1", "2")
    content
  end
end

A.new("123").hi 
# => NoMethodError (undefined method `gsub' for nil:NilClass)

想不通为什么 content 会是 nil,有同学清楚这是什么逻辑吗?

1 楼 已删除

为什么要用实例变量呢?已经声明 attr_reader :content

attr_reader :content 生成了一个 content 方法,在没有歧义的情况下 a = content.gsub 实际是 a = self.content.gsub 的简写,然而当 content 出现在赋值符左边时,content 被解释成一个变量,content = content.gsub 基本等价于content = nil; content = content.gsub.

若非要保持同名的局部变量名,应显式写明 self, 即content = self.content.gsub("1", "2")

另外,即使使用attr_accessor :content生成了content=方法,content = content.gsub 中的 content 也是个变量

3 楼回复的代码版:

?> class A
?>   attr_reader :content
?>   def initialize(content)
?>     @content = content
?>   end
?>   def hi1
?>     content1 = content.gsub("1", "2")
?>   end
?>   def hi2
?>     content = self.content.gsub("1", "2")
?>   end
>> end
=> :hi2
>> 
>> c1 = A.new("123")
=> #<A:0x00007f8d6e0a4878 @content="123">
>> c1.hi1
=> "223"
>> c1.hi2
=> "223"
spike76 回复

明白了,ruby 也有类似 js 的变量提升,感谢😁

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