method_name= 是如何工作的?

How does method_name= work under the hood?

我在 Ruby 中破解了链表的一个简单实现,我遇到了一些非常奇怪的事情。

我创建了一个 List class 和 attr_accessorfirst_node。像这样:

class List
  attr_accessor :first_node

  # Some code here ...
end

然后,在执行方法 delete_at 时出现以下错误

linearly.rb:39:in `delete_at': undefined method `next' for nil:NilClass (NoMethodError) from linearly.rb:81:in `<main>'

这是方法的一部分:

def delete_at(position)
  if position == 0
    deleted_node = first_node
    first_node = first_node.next   # This is line 39.

    return deleted_node
  else
    # More code here ...

我忘记使用 class 变量 @first_node,而是使用了 reader 方法 first_node。然后,我开始想知道为什么在同一行中使用 first_node=first_node returns nil

是否在设置新值之前将 @first_node 设置为 nil

请注意,这段代码工作正常:

def delete_at(position)
  if position == 0
    deleted_node = first_node
    first_node = deleted_node.next

    return deleted_node
  else
    # Some code here ...

编辑:

这就是我调用实现的方式:

list = List.new
list.first_node = Node.new(1)
list.first_node.next = Node.new(2)
list.first_node.next.next = Node.new(3)

puts "Delete at 0"
puts list.delete_at(0)

你确定@first_node已经设置了吗?取消设置时实例变量将 return 为 nil。

class Test
  attr_accessor :foo
  def print_foo
    puts "@foo=[#{@foo}]"
    puts "foo=[#{foo}]"
    puts @foo.nil?
  end
end

t1 = Test.new
t1.foo # => nil
t1.print_foo  # prints "@foo=[]" and "foo=[]" and returns true

这个:

first_node = first_node.next

创建一个名为 first_node 的局部变量。变量声明被提升到 Ruby 范围的顶部,因此您的方法等效于:

def delete_at(position)
  deleted_node = nil # Declare deleted_node and first_node
  first_node = nil   # as local variables.
  if position == 0
    deleted_node = first_node
    first_node = deleted_node.next

    return deleted_node
  else
    # Some code here ...

这意味着您方法中的所有 first_node 引用都将是本地 first_node 变量,而不是 attr_accessor 为您创建的 getter 和设置方法。

要么不要使用与方法名称匹配的变量,要么通过为方法调用提供 self 接收器来明确说明您的意思:

def delete_at(position)
  if position == 0
    deleted_node = self.first_node
    self.first_node = deleted_node.next
    #...