Я уверен, что у Руби есть какие-то средства для вас, чтобы динамически определять константы, но я не буду беспокоиться об этом, потому что это почти на 100% похоже на то, что вы на самом деле не хотите делать. Кажется, вы хотите каким-то образом связать «имя» с экземпляром класса. Это именно то, для чего Hash
.
people_names = ['John', 'Jane', 'Barbara', 'Bob']
people = people_names.each_with_object({}) do |name, ppl|
ppl[name] = Person.new(name)
end
people['John'].name # => 'John'
people['Jane'].name # => 'Jane'
Почему я говорю, что вы просите, вероятно, не то, что вы хотите? Потому что использование метапрограммирования для динамического создания и динамического чтения из локальных переменных / констант / переменных экземпляра, как правило, не одобряется при профессиональном развитии. Возможно, для ваших собственных проектов, для экспериментов. Тем не менее, для любого проекта в составе команды, когда вы начинаете использовать функции метапрограммирования, чтобы динамически добавлять эти значения и ссылаться на них (возможно, напрямую, возможно, косвенно позже), все хорошо, но когда вы пытаетесь выяснить, что происходит, выпочти никогда не будет в состоянии выяснить, откуда эти вещи определены / исходят, если массив с динамическими именами не будет жестко закодирован. И если это жестко запрограммировано, почему вы не можете просто создать константы / переменные / цели непосредственно в коде? Это значительно лучше, чем динамически делать это.
# this is a fake API to demonstrate
# let's assume this is what you want
PEOPLE_NAMES = ['John', 'Jane']
PEOPLE_NAMES.each do |name|
const_def(name, Person.new)
end
get_person('Jane').do_something # maps to const_get('Jane').do_something
get_person(PEOPLE_NAMES[0]).do_something
John.do_something
Если вы хотите, чтобы вышесказанное, почему вы не можете просто сделать:
John = Person.new
Jane = Person.new
John.do_something
Последнее выглядит намного яснее, все еще может бытьдинамически просматривается, но имеет жестко заданное определение, которое можно легко использовать при отладке.
Это моя рекомендация и ответ. Я уверен, что ты не хочешь делать то, что просишь. Hash
полностью соответствует потребностям, которые вы желаете, он интенсивно используется для подобных целей и тесно связан с ним, я рекомендую вам попробовать и заставить это работать в соответствии с вашими потребностями, а затем попытаться выяснить, как решить проблему, которую вы специально хотите получитьответ тоже.
РЕДАКТИРОВАТЬ
Как действительно забавное дополнение, вы можете сделать несколько действительно крутых динамических вещей с Hash
, которые здесь не приводят ктонны путаницы, если вам не удалось скрыть, откуда взялся хэш. Но вы можете сделать что-то вроде:
people = Hash.new { |h, k| h[k] = Person.new(k) }
# right now, people contains no actual people
people['John'].name # => 'John'
# now people contains one Person instance
Это круто по двум причинам: 1) Вам не нужно иметь список для генерации хеша, поэтому, если вы получите имена после создания хеша, это нормально, вы можетепросто добавьте их, указав имя пользователя и 2) Будучи ленивым, он будет использовать только ту память, которая вам нужна. Если вы предварительно загрузили хеш со всеми четырьмя людьми, а затем получили доступ к данным только от двух людей, вы потратили впустую пространство, необходимое для неиспользованных экземпляров 2 Person
, так что это позволяет вам использовать только столько, сколько вам нужно, и в противном случае предлагает вам все то же самоевыгоды.