Почему интерпретатор ruby ведет себя так неадекватно?

Я новичок в Ruby и в ходе выполнения одного из тестовых заданий мне нужно было расширить class Module следующим образом:
class Module
	def method
		self.class_eval{@@var = 1}
		self.class_eval{p @@var}
		p self.class_variable_get(:@@var)#1
		p self.class.class_variable_get(:@@var)#2
	end
end

NewClass = Class.new do
end

NewClass.method


В строчке #1 появится ошибка ErrorName
но #2 работает нормально (но мы добавляем переменную класса в новый созданный класс, то есть self, а не его class)

Раcсмотрев еще один пример, я вообще перестал что-то понимать
class Module
	def set_class_var(value)
		self.class_eval{@@var = value}
	end

	def get_class_var()
		self.class_variable_get(:@@var)
	end

	def print_class_var
		self.class_eval{p @@var}
	end
end


c = Class.new
c2 = Class.new


c.set_class_var(10)
c.print_class_var #10

c2.print_class_var#10


Скажите где я туплю, так как сам понять не могу.
  • Вопрос задан
  • 2629 просмотров
Решения вопроса 1
Vakiliy
@Vakiliy
По первому примеру. method определен для потомков (экземпляры, инстансы) класса Module, Class наследуется от класса Module поэтому в нем этот метод тоже есть.

NewClass является потомком класа Class, т.е NewClass.class == Class
self - указатель на текущий объект, соответвенно область видимости текущий объект.

Так как method является методом потомков, то и область видимости self в будет являться область видимости потомков.

Теперь, переменная класса @@var определяется в Module, по наследованию доступна в Class, и будет доступна в методах как самого класса, так и в метододах для потомков, соответвенно доступна в method. (Можно устроть обменник для потоков, если поместить в мутекс, или сделать счетчик скока потомков порадилось, ну это так, для примера).

Что происходит при вызове NewClass.method - self указываеть на NewClass, соответвенно self.class_variable_get(:@@var) пытается получить доступ к переменной класса опреленной в NewClass но так как ее там нет, получаем ошибку номер 1.

p self.class.class_variable_get(:@@var) - self.class устанавливает область видимости Class (self указывает на NewClass) - ошибки не происходит, переменная класса определена.

По второму примеру, как и говорил ранее, переменная класса доступна как для методов класса, так и для методом потомков определенных в классе, и является одной и тойже переменной, поэту при изменении в одном месте, она меняется и в другом.

Объяснил как смог, вобщем :)

Поподробней можно почитат, например, тут
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы