Как получить доступ к атрибуту класса, установленному class_exec()

Вот что я пытаюсь сделать:

class Foo; end

Foo.class_exec do
  class_variable_set(:@@x, 42)
  def get
    @@x # runtime error here!
  end
end

puts Foo.new.get

Я получаю (Ruby 3.2.1):

$ ruby a.rb
a.rb:6:in `get': class variable access from toplevel (RuntimeError)
    from a.rb:10:in `<main>'

Как мне прочитать это @@x, которое я только что установил?

Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Шаг 1: Создание приложения Slack Чтобы создать Slackbot, вам необходимо создать приложение Slack. Войдите в свою учетную запись Slack и перейдите на...
2
0
77
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Есть class_variable_get , но поскольку это метод Module, вам нужно вызвать его в классе или singleton_class получателя:

Foo.class_exec do
  class_variable_set(:@@x, 42)
  def get
    self.class.class_variable_get(:@@x)
    # or
    # singleton_class_variable_get(:@@x)
  end
end

Альтернативно, в Ruby вполне нормально повторно открыть класс:

class Foo; end

class Foo
  @@x = 42

  def get
    @@x
  end
end

Обратите внимание, что обычно не рекомендуется использовать переменные класса из-за их неожиданного поведения при наследовании. См. Почему использование переменной класса в Ruby считается «запахом кода»?

поэтому использование @@x просто игнорирует контекст class_exec. это будет ошибкой?

Alex 26.06.2024 02:17

@Алекс, это похоже на Foo.class_exec { Bar = 123 }, который устанавливает константу верхнего уровня Bar вместо Foo::Bar.

Stefan 26.06.2024 09:56

теперь это имеет такой большой смысл. он объясняет поведение переменных класса лучше, чем сравнение их с переменными экземпляра: объясняет наследование, почему они доступны из методов экземпляра и класса, даже объясняет, почему это запах кода (использование констант в качестве переменных). возможно, стоит ответить здесь stackoverflow.com/questions/15773552/…

Alex 26.06.2024 12:20

@Алекс довольно много общего, но есть и различия. Константы имеют лексическую область действия (вложенность), тогда как переменные класса имеют динамическую область действия (наследование).

Stefan 26.06.2024 14:42

Другие вопросы по теме