2017-02-15 4 views
0

Я пытаюсь создать программу, которая будет строить и манипулировать дважды связанным списком в Ruby.Попытка удалить узел из связанного списка и не понимать сообщение об ошибке

До сих пор я смог удовлетворить тест, который говорит мне, что я создал список, но изо всех сил пытаюсь заставить мой метод delete работать.

прямо сейчас мой Rspec тест продолжает говорить мне:

Failure/Error: llist.delete(n3) 
      NameError: 
     undefined local variable or method `current' for #<LinkedList:0x007f85a49ae9b8> 
     Did you mean? current 

, хотя я уверен, что я определить метод

это мой linkedlist.rb файл

require_relative 'node' 

class LinkedList 
    attr_accessor :head 
    attr_accessor :tail 
    bob = [] 
    current = nil 
    # This method creates a new `Node` using `data`, and inserts it at the end of the list. 
    def add_to_tail(node) 
    if(@next) 
     @tail.next = node 
    else 
     @tail= node 
    end 
    end 
# This method removes `node` from the list and must keep the rest of the list intact. 
    def delete(node) 
    current.next [email protected] 
    if current.node = node 
     @head =current.next 
    else 
     while (current.next != nil)&&(current.next.node != val) 
     current = current.next 
     end 
     unless current.next == nil 
     current.next =current.next.next 
     end 
    end 

    end 

это файл компаньона, который устанавливает класс Node

class Node 
    attr_accessor :next 
    attr_accessor :data 

    def initialize(data) 
    @data = data 
    #@next = nil 
    end 
end 

и эти тесты RSpec Я пытаюсь передать

include RSpec 

require_relative 'node' 
require_relative 'linked_list' 

RSpec.describe LinkedList, type: Class do 
    let(:n1) { Node.new("Rob") } 
    let(:n2) { Node.new("Ben") } 
    let(:n3) { Node.new("Mike") } 
    let(:llist) { LinkedList.new } 

    describe "#add_to_tail" do 
    it "adds a Node to the tail" do 
     llist.add_to_tail(n1) 
     expect(llist.tail).to eq n1 
     llist.add_to_tail(n2) 
     expect(llist.tail).to eq n2 
    end 
    end 
    describe "#delete" do 
    before do 
     llist.add_to_tail(n1) 
     llist.add_to_tail(n2) 
     llist.add_to_tail(n3) 

it "removes the correct node of a list properly" do 
     llist.delete(n1) 
     expect(llist.head).to eq n2 
     llist.delete(n3) 
     expect(llist.tail).to eq n2 
    end 

ответ

2

вы определяете ток и боб в рамках класса, однако в рубиновой переменной области видимости класса устанавливается с двойным @@. Но это вызовет проблемы при использовании нескольких связанных списков, поэтому вы не хотите использовать переменные класса в этом случае. Поэтому лучшим способом было бы установить переменную экземпляра @current и @bob для экземпляра LinkedList. Я бы предложил сделать следующее:

изменения тока и боб на это:

attr_accessor :current 
attr_accessor :bob 

, что attr_accessor делает, это создает @current переменную экземпляра, а также определяет два метода для вас, геттер current и сеттер current=.

следующий шаг, чтобы установить их на ноль и массив, чтобы использовать метод инициализации, добавьте в ваш LinkedList класс:

def initialize(*args) 
    @current = nil 
    @bob = [] 
end 

хотя когда экземпляр @current создан, он уже будет установлен до nil, поэтому первая строка инициализации на самом деле избыточна, я просто добавил ее для удобства отображения, чтобы было легче увидеть, что происходит по сравнению с вашим текущим кодом.

+1

Переменные экземпляра на уровне класса имеют префикс '@@', но использование этих параметров может быть проблематичным. Лучше использовать переменные экземпляра класса, те, которые определены в области класса, если это необходимо. – tadman

+0

действительно, поэтому я рекомендую использовать переменные экземпляра, но переменные экземпляра класса и переменные класса различны, переменные класса заданы с помощью @@, переменные экземпляра класса класса задаются с помощью одного @, но определяются через мета- класс с чем-то вроде 'class << self; attr_accessor: текущий; end', которые разделяют переменную для унаследованных классов, но экземпляры одного и того же класса по-прежнему будут проблематичными. И переменные экземпляра с stadard @. Я знаю, что я немного придирчив, но просто хотел подчеркнуть, что классы Class, Class-leve instancel и экземпляры разные. –

+1

Здесь объясняется довольно неплохо: http://www.railstips.org/blog/archives/2006/11/18/class-and-instance-variables-in-ruby/ –

Смежные вопросы