Модуль, содержащий методы для подсчета экземпляров класса

У меня есть задача:

  • Создать модуль InstanceCounter, содержащий метод класса и инстанс-метод, который подключаются автоматически при вызове include в классе:
  • Метод класса который возвращает кол-во экземпляров данного класса
  • Инастанс-метод который увеличивает счетчик кол-ва экземпляров класса и который можно вызвать из конструктора.
  • Примечание: инстансы подклассов могут считатья по отдельности, не увеличивая счетчик инстансов базового класса.

Мои познания сводятся к следующему:

  • Метод класса можно вызвать на объекте класса: MyClass.my_metod
  • Инстанс метод вызывается на экземпляре класса: MyClass.new.my_metod
  • Без использования модуля я сделал вот так:
class MyClass
  @@num = 0

  def initialize
    num_plus
  end

  def self.num
    @@num
  end

  def num_plus
    @@num += 1
  end
end
  • С модулем есть проблема. include MyModule - можно подмешать инстанс методы в класс. extend MyModule - можно подмешать методы класса в класс. Я нашел как это сделать используя один модуль:
module MyModule

  def self.included(base) # Вот эта строка не совсем понятно как работает
    base.extend(ClassMethods)
  end

  def register_instance
    puts 'instance_metod'
  end

  module ClassMethods
    def instances
      puts 'class metod'
    end
  end
end

Вопрос: как бы я ни пытался куда либо запихнуть переменную класса, и в класс, и в модуль, где бы ее не объявлял, инициализировал, ничего не получается; то один метод, то другой ее не видит, вылезает ошибка "не инициализированная переменная" или вообще, перестает быть видимым один из методов. Видимо я пропускаю в своей логике что-то важное. Подскажите, пожалуйста, в какую сторону копать?


Ответы (1 шт):

Автор решения: Василиса

Это делается через Module#class_variable_set (get)

module MyModule
  def self.included(base) 
    base.class_variable_set('@@instances_count', 0)
    base.extend(ClassMethods)
  end

  def increase_instances_count
    @@instances_count += 1
  end 

  module ClassMethods
    def instances_count
      class_variable_get('@@instances_count')
    end
  end
end

class MyClass
  include MyModule

  def initialize
    increase_instances_count
  end
end

Вот здесь очень классно рассказано про include и extend

→ Ссылка