链接列表类初始化错误

时间:2017-05-10 03:46:22

标签: ruby linked-list minitest

对于具有定义方法的类,我有require。我甚至将它放在attr_accessor中,我非常确定是否完全过剩。但无论我在何处或如何表达,我都无法摆脱这个错误NoMethodError: undefined method "next_node" for nil:NilClass。我正在运行minitest来使用TDD,并且在这一点上超级挂了。

编辑我在测试nil

时尝试返回list.head.next_node
require './lib/node'
class LinkedList
  attr_accessor :head,
                :next_node

  def initialize(head = nil)
    @head = head
    @next_node = next_node
  end

  def append(sound)
    #@next_node = nil
    @head = Node.new(sound)
    sound
  end

end

这是我的测试方法

def test_does_head_move_value_to_next_node
    list = LinkedList.new
    list.head.next_node
    # assert_nil list.head.next_node
end

1 个答案:

答案 0 :(得分:1)

LinkedList.new会调用您的initialize;未传输head参数,因此将分配默认值nil@head = head会将nil存储在@head属性中。

稍后,您的list.head使用(根本不是必需的)访问者,并返回之前存储的nil。然后.next_node被发送到nil,但NilClass没有定义这样的方法。为了让list.head.next_node调用您的next_node方法,@head需要是LinkedList个对象,而不是nil

如果您希望保护自己不受此影响,可以使用:

list.head.next_node if list.head

或使用Ruby 2.3引入的安全导航操作符&.,它将检查左侧是nil并返回nil(如果是)(如果没有则调用方法) :

list.head&.next_node

编辑:还有一个微妙的错误,在您的代码中是无害的,但在某些其他情况下可能会完全出乎意料。

@next_node = next_node

由于您尚未在next_node方法中定义initialize变量,因此Ruby会断定您希望调用访问者。此访问者将返回@next_node,因此您最终会执行@next_node = @next_node。幸运的是,@next_node已经以nil开头,所以尽管完全没必要,但这项任务至少不会失败。

但是,如果你自己定义了访问者,请这样说:

def next_node
  @next_node ||= LinkedList.new
end

(返回@next_node;如果是nil,则首先创建一个新的空LinkedList,将其设置为@next_node然后返回),然后你就进入真的很麻烦,因为如果你现在说LinkedList.new,你会尝试分配给@next_node一个LinkedList.new,它会尝试分配给@next_node LinkedList.new ,它会尝试分配给@next_node一个LinkedList.new,这将... Ctrl-C