Подтвердить что ты не робот

Динамическое добавление атрибутов к объекту Ruby

У меня есть созданный объект, и я хочу, на основе некоторой условной проверки, добавить некоторые атрибуты к этому объекту. Как я могу это сделать? Объяснить, что я хочу:

A=Object.new
if(something happens)
{
  #make A have another attibute say age
  #& store something in A.age

}
4b9b3361

Ответ 1

Прежде всего, дело в рубине заключается в том, что он позволяет использовать другой синтаксис, который широко используется рубиновыми кодировщиками. Капитализированные идентификаторы - это классы или константы (спасибо sepp2k за его комментарий), но вы пытаетесь сделать его объектом. И почти никто не использует {}, чтобы отметить многострочный блок.

a = Object.new
if (something happens)
  # do something
end

Я не уверен, в чем ваш вопрос, но у меня есть идея, и это было бы решением:

Если вы знаете, какие атрибуты может иметь этот класс, и он ограничен, вы должны использовать

class YourClass
  attr_accessor :age
end

attr_accessor :age не подходит для:

def age
  @age
end
def age=(new_age)
  @age = new_age
end

Теперь вы можете сделать что-то вроде этого:

a = YourClass.new
if (some condition)
  a.age = new_value
end

Если вы хотите сделать это полностью динамически, вы можете сделать что-то вроде этого:

a = Object.new
if (some condition)
  a.class.module_eval { attr_accessor :age}
  a.age = new_age_value
end

Ответ 2

Это добавляет атрибут только к объекту:

a = Object.new
if (something happens)
  class << a
    attr_accessor :age
  end
  a.age = new_age_value
end

Ответ 3

Вы можете использовать OpenStruct:

a = OpenStruct.new
if condition
    a.age = 4
end

Или просто используйте простой старый хэш.

Ответ 4

Если имя атрибута известно в момент написания кода, вы можете сделать то, что было предложено уже:

class A
end

a = A.new
a.age = 20 # Raises undefined method `age='

# Inject attribute accessors into instance of A
class << a
  attr_accessor :age
end

a.age = 20 # Succeeds
a.age # Returns 20

b = A.new
b.age # Raises undefined method, as expected, since we only modified one instance of A

Однако, если имя атрибута является динамическим и известно только во время выполнения, вам придется называть attr_accessor несколько иначе:

attr_name = 'foo'

class A
end

a = A.new
a.foo = 20 # Raises undefined method `foo='

# Inject attribute accessors into instance of A
a.instance_eval { class << self; self end }.send(:attr_accessor, attr_name)

a.foo = 20 # Succeeds
a.foo # Returns 20

Ответ 5

Вы можете использовать instance_variable_set для установки переменной в экземпляре класса Object (и instance_variable_get для ее получения.) Класс Object не имеет никаких атрибутов, которые вы можете установить напрямую.

Однако я подозреваю, что это не лучшее решение для того, чего вы пытаетесь достичь; это не норма, чтобы непосредственно работать с классом Object, а скорее определять или использовать классы, которые наследуют от него, которые имеют атрибуты, с которыми вы хотите работать.