Это распространенная ошибка, допущенная Java-кодерами и Ruby, и один из больших концептуальных прыжков, которые мне пришлось осмыслить. Сначала это кажется странным, но на самом деле это один из круче аспектов Ruby - весь код исполняемый, включая определения классов.
Итак, переменные экземпляра должны быть объявлены внутри методов. Это связано с тем, как оценивается «я». «Я» - текущий объект. Интерпретатор сначала будет искать вызовы методов и ссылки на переменные в «self»:
class Fish
@var = "foo" # here 'self' == Fish, the constant which contains the class object
def foo
# do foo
end
end
fish = Fish.new
fish.foo # here 'self' == fish, an instance of Fish
В определении класса 'self' задается как определяемый объект класса, поэтому любые ссылки в определении класса будут ссылаться на этот объект класса, в данном случае Fish.
Когда метод вызывается для экземпляра Fish, однако, self устанавливается как получатель вызова, конкретный экземпляр Fish. Таким образом, вне определения метода self является объектом класса. Внутри метода self является экземпляром получателя. Вот почему @var вне определения метода больше похож на статическую переменную в Java, а @var внутри определения метода - это переменная экземпляра.