2013-04-14 3 views
0

Я надеюсь, что кто-то может пролить свет на ошибку, которую я получаю ниже. Я определяю переменный экземпляр в родительском классе Node и хочу получить доступ и изменить его в подклассе AddSubNode всякий раз, когда я пытаюсь получить доступ @code я получаю эту ошибку:Доступ к переменной экземпляра в подклассах

'code': undefined method `<<' for nil:NilClass (NoMethodError) 

Я должен быть недопонимание модели наследования в Ruby, но я подумал, что я могу это сделать.

class Node 
    attr_accessor :code 

    def initialize 
    @code = [] 
    end 
end 

class AddSubNode < Node 
    def initialize op, l, r 
    @op = op 
    @l = l 
    @r = r 
    end 

    def code 
    @code << 1 # error: `code': undefined method `<<' for nil:NilClass (NoMethodError) 
    @code 
    end 

    def to_s 
    "#{@l} #{@op} #{@right}" 
    end 
end 

ответ

4

Вам необходимо вызвать супер инициализатор в инициализаторе подкласса.

class AddSubNode < Node 
    def initialize op, l, r 
    super() 
    @op = op 
    @l = l 
    @r = r 
    end 
... 

редактировать: забыли скобку

+0

интересный, по какой-то причине я предположил, что это было сделано неявно. Благодаря! –

+0

Нет, методы Ruby не косвенно называют их реализацию суперкласса. Это не имеет смысла, и ни один другой язык не делает этого. Могу я спросить, почему вы предположили это? –

+0

@ JörgWMittag Мне кажется, что мне нравится, в этом конкретном сценарии у меня есть ~ 100 подклассов 'Node', мне пришлось вернуться в каждом из них и добавить' super() '. Не могли бы вы объяснить, почему это не имеет смысла для этого неявно? –

2

При переопределении метода initialize в подклассе, вы перезаписать оригинал. Следовательно, переменная экземпляра @code никогда не инициализируется, и вы вызываете ошибку при вызове @code << 1.

Вызов super() из метода initialize в ваш подкласс (эффективно называемый его родителем) или использование @code << 1 unless @code.nil? - это несколько способов устранения ошибки.

+0

Это не имеет смысла. –

+0

@HunterMcMillen Что вы не понимаете? – rudolph9

+1

Что означает rudolph, так это то, что подкласс автоматически наследует супер инициализатор (который обычно вызывается). Но с вашим 'def initialize op, l, r' в подклассе, вы перезаписываете его новой реализацией. – tessi

1

Здесь я просто попытался дать вам визуализацию для тестирования таких сценариев.

class Node 
    attr_accessor :code 

    def initialize 
    @code = [] 
    end 
end 

class AddSubNode < Node 
    def initialize op, l, r 
    @op = op 
    @l = l 
    @r = r 
    end 

    def code 
    @code << 1 # error: `code': undefined method `<<' for nil:NilClass (NoMethodError) 
    @code 
    end 

end 

ob = AddSubNode.new(1,2,3) 
p ob.instance_variables #=> [:@op, :@l, :@r] 
p ob.instance_variable_defined?(:@code) #=> false 
p ob.instance_variable_set :@code,[12] #=> [12] 
p ob.instance_variable_defined?(:@code) #=> true 
p ob.instance_variable_get :@code #=> [12] 
p ob.instance_variables #=> [:@op, :@l, :@r, :@code] 
p ob.code #=> [12, 1] 
Смежные вопросы