Просто для удовольствия - добавьте методы к объекту через блок - PullRequest
2 голосов
/ 12 мая 2011

Просто для забавы, опять же, но можно ли как-нибудь взять блок, содержащий определения методов, и добавить их в объект?Следующее не работает (я никогда не ожидал), но просто чтобы вы поняли, с чем я играю.

Я знаю, что могу открыть класс с помощью class << existing_object идобавить методы таким образом, но есть ли способ для кода передавать эту информацию в блоке?

Я думаю, я пытаюсь заимствовать немного Java-мышления здесь.

def new(cls)
  obj = cls.new
  class << obj
    yield
  end
  obj
end

class Cat
  def meow
    puts "Meow"
  end
end

cat = new(Cat) {
  def purr
    puts "Prrrr..."
  end
}

cat.meow
  # => Meow

# Not working
cat.purr
  # => Prrrr...

РЕДАКТИРОВАТЬ|Вот рабочая версия выше, основанная на ответе edgerunner:

def new(cls, &block)
  obj = cls.new
  obj.instance_eval(&block)
  obj
end

class Cat
  def meow
    puts "Meow"
  end
end

cat = new(Cat) {
  def purr
    puts "Prrrr..."
  end
}

cat.meow
  # => Meow

cat.purr
  # => Prrrr...

Ответы [ 2 ]

4 голосов
/ 12 мая 2011

Вы можете использовать class_eval (также называемый module_eval) или instance_eval для оценки блока в контексте класса / модуля или экземпляра объекта соответственно.

class Cat
  def meow
    puts "Meow"
  end
end

Cat.module_eval do
  def purr
    puts "Purr"
  end
end

kitty = Cat.new
kitty.meow #=> Meow
kitty.purr #=> Purr

kitty.instance_eval do
  def purr
    puts "Purrrrrrrrrr!"
  end
end

kitty.purr #=> Purrrrrrrrrr!
2 голосов
/ 12 мая 2011

Да

Я подозреваю, что вы подумали об этом и искали какой-то другой способ, но на всякий случай ...

class A
  def initialize
    yield self
  end
end

o = A.new do |o|
  class << o
    def purr
      puts 'purr...'
    end
  end
end

o.purr
=> purr...

Для записи,это не обычный способ динамического добавления метода.Как правило, динамический метод запускает жизнь как сам блок, см., Например, * Module # define_method *.

...