Наследовать переменные экземпляра класса на Ruby? - программирование
Подтвердить что ты не робот

Наследовать переменные экземпляра класса на Ruby?

Я хочу, чтобы дочерний класс наследовал переменную экземпляра класса от родителя, но я не могу понять ее. В основном я ищу такую ​​функциональность:

class Alpha
  class_instance_inheritable_accessor :foo #
  @foo = [1, 2, 3]
end

class Beta < Alpha
  @foo << 4
  def self.bar
    @foo
  end
end

class Delta < Alpha
  @foo << 5
  def self.bar
    @foo
  end
end

class Gamma < Beta
  @foo << 'a'
  def self.bar
    @foo
  end
end

И затем я хочу, чтобы это выводилось следующим образом:

> Alpha.bar
# [1, 2, 3]

> Beta.bar
# [1, 2, 3, 4]

> Delta.bar
# [1, 2, 3, 5]

> Gamma.bar
# [1, 2, 3, 4, 'a']

Очевидно, что этот код не работает. В основном я хочу определить значение по умолчанию для переменных экземпляра класса в родительском классе, который наследует его подклассы. Изменение подкласса будет значением по умолчанию, а затем для под-подкласса. Я хочу, чтобы все это произошло без изменения одного значения класса, влияющего на его родителя или братьев и сестер. Class_inheritable_accessor дает именно то, что я хочу... но для переменной класса.

Я чувствую, что, возможно, я слишком много спрашиваю. Любые идеи?

4b9b3361

Ответ 1

Используйте mixin:

module ClassLevelInheritableAttributes
  def self.included(base)
    base.extend(ClassMethods)    
  end

  module ClassMethods
    def inheritable_attributes(*args)
      @inheritable_attributes ||= [:inheritable_attributes]
      @inheritable_attributes += args
      args.each do |arg|
        class_eval %(
          class << self; attr_accessor :#{arg} end
        )
      end
      @inheritable_attributes
    end

    def inherited(subclass)
      @inheritable_attributes.each do |inheritable_attribute|
        instance_var = "@#{inheritable_attribute}"
        subclass.instance_variable_set(instance_var, instance_variable_get(instance_var))
      end
    end
  end
end

Включение этого модуля в класс дает два метода класса: inheritable_attributes и inherited.
Метод унаследованного класса работает так же, как и метод self.included в показанном модуле. Всякий раз, когда класс, который включает этот модуль, получает подклассы, он устанавливает переменную экземпляра класса для каждой из объявленных переменных класса наследуемого экземпляра класса (@inheritable_attributes).

Ответ 2

То, что я сделал в моем проекте для использования resque, - это определение базы

class ResqueBase
  def self.inherited base
    base.instance_variable_set(:@queue, :queuename)
  end
end

В других дочерних заданиях экземпляр очереди будет установлен по умолчанию. Надеюсь, это поможет.

Ответ 3

Rails имеет это встроенное в фреймворк как метод, называемый class_attribute. Вы всегда можете проверить источник для этого метода и создать свою собственную версию или скопировать ее дословно. Единственное, на что нужно обратить внимание, это то, что вы не меняете изменяемые элементы на месте.