kzen.dev
  • Вопросы
  • Метки
  • Пользователи
Оповещения
Вознаграждения
Регистрация
После регистрации, сможете получать уведомления об ответах и комментариях на Ваши вопросы.
Вход
Если у Вас уже есть аккаунт, войдите чтобы проверить новые уведомления.
Тут будут вознаграждения за добавленные вопросы, ответы и комментарий.
Дополнительно
Источник
Редактировать
Анонимный пользователь
Вопрос

Ruby: Наследование кода, работающего с переменными класса

Ситуация: У меня есть несколько классов, каждый из которых должен содержать переменную с хэшем конфигурации; для каждого класса свой хэш, но одинаковый для всех экземпляров класса.

Сначала я пытался сделать вот так

class A
  def self.init config
    @@config = config
  end

  def config
    @@config
  end
end

class B < A; end
class C < A; end

Но вскоре заметил, что так не получится, потому что @@config хранится в контексте A, а не B или C, таким образом:

B.init "bar"
p B.new.config  # => "bar"
p C.new.config  # => "bar" - which would be nil if B had it's own @@config

C.init "foo"
p B.new.config  # => "foo" - which would still be "bar" if C had it's own @@config
p C.new.config  # => "foo"

Я подумал о том, чтобы использовать его следующим образом:

modules = [B, C]
modules.each do |m|
  m.init(@config[m.name])
end
# ...
B.new  # which should then have the correct config

Теперь мне понятно, почему так происходит, но я не уверен в причине, по которой это происходит именно так.

Не может ли это работать и в обратную сторону, удерживая переменную класса в контексте подкласса?

Меня также раздражает тот факт, что self всегда является подклассом, даже когда вызывается 'в' суперклассе. Исходя из этого, я сначала ожидал, что код из суперкласса "выполняется в контексте" подкласса.

Буду очень признателен за разъяснения по этому поводу.

С другой стороны, скорее всего, мне придется смириться с тем, что это работает именно так, и что я должен найти другой способ сделать это.

Есть ли "мета" способ сделать это? (Я пытался использовать class_variable_set и т.д., но безуспешно).

Или, может быть, вся идея этого метода 'init' изначально ошибочна, и есть какой-то другой "паттерн" для этого?

Я мог бы просто сделать @@config хэшем, хранящим все конфигурации, и всегда выбирать нужную, но мне кажется это немного неудобным... (разве наследование не предназначено для решения подобных проблем? ;)

42 2009-08-09T13:12:41+00:00 1
 MPelletier
MPelletier
Редактировал вопрос 22-го июня 2012 в 2:11
Программирование
class
ruby
inheritance
metaprogramming
Решение / Ответ
J&#246;rg  W Mittag
Jörg W Mittag
9-го августа 2009 в 1:52
2009-08-09T13:52:58+00:00
Дополнительно
Источник
Редактировать
#9351923

Переменные @@variables не являются переменными класса. Это переменные иерархии классов, т.е. они разделяются между всей иерархией классов, включая все подклассы и все экземпляры всех подклассов. (Было предложено думать о @@переменных'' как о$$переменных'', потому что они имеют больше общего с $globals'', чем с@ivars''. Так будет меньше путаницы. Другие пошли дальше и предлагают просто удалить их из языка).

В Ruby нет переменных класса в том смысле, в каком они есть, скажем, в Java (где они называются статическими полями). Ему не нужны переменные класса, потому что классы - это тоже объекты, и поэтому они могут иметь экземплярные переменные, как и любой другой объект. Все, что вам нужно сделать, это удалить лишние @. (И вам придется предоставить метод доступа для переменной экземпляра класса).

class A
  def self.init config
    @config = config
  end

  def self.config # This is needed for access from outside
    @config
  end

  def config
    self.class.config # this calls the above accessor on self's class
  end
end

Давайте немного упростим это, поскольку A.config явно является просто считывателем атрибутов:

class A
  class << self
    def init config
      @config = config
    end

    attr_reader :config
  end

  def config
    self.class.config
  end
end

И, на самом деле, A.init - это просто писатель с забавным именем, поэтому давайте переименуем его в A.config= и сделаем его писателем, что в свою очередь означает, что наша пара методов теперь просто пара аксессоров. (Поскольку мы изменили API, тестовый код также должен измениться, очевидно).

class A
  class << self
    attr_accessor :config
  end

  def config
    self.class.config
  end
end

class B < A; end
class C < A; end

B.config = "bar"
p B.new.config  # => "bar"
p C.new.config  # => nil

C.config = "foo"
p B.new.config  # => "bar"
p C.new.config  # => "foo"

Однако я не могу отделаться от ощущения, что есть что-то более фундаментально неправильное в дизайне, если вам это вообще нужно.

109
0
Похожие сообщества 6
Чат по Руби
Чат по Руби
2 350 пользователей
Чат-болталка для учеников руби-школы и не только. Сайт школы: https://rubyschool.us Правила: https://telegra.ph/Pravila-chata-Rubi-shkoly-03-13 или тут https://graph.org/Pravila-chata-Rubi-shkoly-03-13
Открыть telegram
RubyRush.ru
RubyRush.ru
2 295 пользователей
Дружелюбный чат для начинающих программистов и учеников rubyrush.ru, обсуждаем программирование, ruby и т. п. Правила чата https://telegra.ph/22-09-05-3 Популярные вопросы (с ответами) https://telegra.ph/22-09-17-4 💎🦜
Открыть telegram
pro.rb (Ruby/Rails / RU)
pro.rb (Ruby/Rails / RU)
1 183 пользователей
Язык программирования Ruby: https://ru.wikipedia.org/wiki/Ruby Вакансии: @rubyjob
Открыть telegram
Ruby — вакансии и аналитика
Ruby — вакансии и аналитика
358 пользователей
Публикуем вакансии и запросы на поиск работы по направлению Ruby. Full-time, part-time, remote и разовые подработки. Обмен инсайдами и аналитикой на рынке труда. Тематическое общение: @ruby_ru См. также: @python_jobs, @nodejs_jobs, @devops_jobs
Открыть telegram
Ruby, Rails, Hanami | dry-rb
Ruby, Rails, Hanami | dry-rb
345 пользователей
Открыть telegram
Ruby Talks
Ruby Talks
255 пользователей
Национальная Флеймотека
Открыть telegram
Добавить вопрос
Категории
Все
Технологий
Культура / Отдых
Жизнь / Искусство
Наука
Профессии
Бизнес
Пользователи
Все
Новые
Популярные
1
Ilya Smirnov
Зарегистрирован 6 дней назад
2
Денис Васьков
Зарегистрирован 1 неделю назад
3
Dima Patrushev
Зарегистрирован 1 неделю назад
4
sirojidddin otaboyev
Зарегистрирован 2 недели назад
5
Елена Гайдамамакинат
Зарегистрирован 2 недели назад
KO
RU
© kzen.dev 2023
Источник
stackoverflow.com
под лицензией cc by-sa 3.0 с атрибуцией