Может ли класс в ruby хранить количество экземпляров объектов, используя @class_instance_variable, а не @@class_variable?
Я пытаюсь вести подсчет экземпляров объектов данного класса внутри класса, который определяет эти объекты.
Прежде всего, я знаю об отражении кода и ObjectSpace.each_object, но я бы предпочел не использовать отражение и позволить самому классу "заботиться" о себе.
Я оглянулся вокруг, и все найденные решения, похоже, используют @@class_variables в определении класса, как, например, принятый ответ на этот вопрос: как получить экземпляры классов в Ruby?
Хотя я продолжал читать, я обнаружил, что переменные класса в ruby могут вести себя очень плохо в некоторых ситуациях... главная причина заключается в следующем:
Переменная класса, определенная на верхнем уровне программы, наследуется всеми классами. Он ведет себя как глобальная переменная.
источник и дополнительная информация здесь: http://ruby.runpaint.org/variables
Итак, я попытался закодировать класс, который хранит количество своих экземпляров объектов внутри себя, используя переменную экземпляра класса вместо переменной класса, и, похоже, это работает нормально, но так как я все еще изучаю этот "углубленный" язык Темы, которые я хотел бы спросить, если код, который я написал, является правильным и / или имеет смысл:
class Pizza
@orders = 0
def self.new
@orders += 1
end
def self.total_orders
@orders
end
end
new_pizza = Pizza.new #=> 1
special_pizza = Pizza.new #=> 2
fav_pizza = Pizza.new #=> 3
Одно из моих сомнений в том, что, переопределяя метод Pizza.new, я "удаляю" некоторую важную функциональность исходного метода.new? (Что обеспечивает оригинальный метод.new? Как я могу "проверить" код метода, используя отражение?) Что еще я делаю неправильно или полностью неправильно в своем подходе и почему?
Спасибо
редактировать: забыл добавить этот важный бит:
Чтобы лучше ограничить область действия, я бы хотел, чтобы класс Pizza мог рассчитывать только во время создания объекта и не иметь метода setter для своей переменной класса @instance, к которой можно обращаться в любое время в коде (Pizza.count = 1000). Вот почему я пытался переопределить "новый".
Я думаю, что это самая сложная часть, которая заставляет меня задаться вопросом, верен ли мой подход в правильном направлении, или если я просто должен прекратить так много полагаться на эти языковые механизмы и вместо этого добавить себе некоторую логику, чтобы подсчет происходил, только если объект класс Pizza вошел в ObjectSpace..
Я просто ищу более элегантный, не раздутый способ получить это, используя языковые функции.
В любом случае помощь будет оценена..
Еще раз спасибо.
2 ответа
Вам не нужно переопределять новое. Попробуй это:
class Pizza
@count = 0
class << self
attr_accessor :count
end
def initialize
self.class.count += 1
end
end
Pizza.new
Pizza.new
puts Pizza.count
Обратите внимание, что Pizza.count
не будет падать, когда пицца собирается мусором, и не будет подниматься, когда они dup
редактор
Чтобы ответить на ваши другие вопросы: я не уверен, как вы можете проверить new
метод, но он, вероятно, написан на C, поэтому вы должны посмотреть в исходном коде Ruby. Я думаю, что это в основном делает это.
def new(*args, &block)
o = allocate
o.initialize(*args, &block)
o
end
Вы могли бы сойти с рук с переопределением нового, пока вы звонили super
в какой-то момент. (Не говорю, что это хорошая идея, но, например:
class Foo
def self.new
# do whatever stuff you want here
super
end
end
)
Вы правы. использование переменных класса несколько раз ошеломляет. я всегда забываю, если наследуется или нет и т. д.
ваш подход правильный, но...
НИКОГДА не переопределять new
воплощать в жизнь initialize
вместо! он будет вызван во время процесса инициализации каждого объекта. см. документы здесь: http://apidock.com/ruby/v1_9_3_125/Class/new