Я хотел бы написать метод в ruby, который принимает класс с определенными методами и изменяет его поведение, добавляя методы или изменяя, как работают существующие методы. Я хотел бы сделать это таким образом, чтобы не изменять базовый класс, поэтому я хочу, чтобы функция, которая принимает класс, и возвращает новый модифицированный класс, не нанося вреда первому классу. Я уверен, что это возможно, но я не уверен, с чего начать.Расширения класса ruby
ответ
У вас есть несколько вариантов:
- вы можете использовать
x = Class.new(Parent) { def meth; puts "hello"; super; puts "bye"; end }
динамически определять класс и переопределить методы (& определить новые) - вы можете использовать
Delegator
Так Например, если вы хотите динамически создавать классы, которые регистрировали определенные вызовы методов:
class Class
def logging_subclass(*methods)
Class.new(self) do
methods.each do |method|
define_method(method) do |*args,&blk|
puts "calling #{method}"
ret = super(*args,&blk)
puts "#{method} returned #{ret.inspect}"
ret
end
end
end
end
end
class One
def foo
"I'm foo!"
end
end
# this prints nothing
One.new.foo #=> returns :foo
# this prints:
# > calling foo
# > foo returned "I'm foo!"
One.logging_subclass(:foo).new.foo #=> returns :foo
Обратите внимание, что вам нужно ruby 1.9 для поддержки захвата do |&blk|
(захват блоков в аргументах блока).
Я предлагаю использовать inheritance или a mixin; на мой взгляд, использование mixin было бы более разумной идеей, хотя использование наследования легче для новичков.
Помните, что вы всегда можете унаследовать класс и изменить поведение или обернуть его новым кодом.
class Mammal
def speak
"..."
end
end
class Cat < Mammal
def speak
"meow"
end
end
class Lion < Cat
def speak
"get ready for a big " + super + "!"
end
end
module Asexual_Critter
def reproduce(critter_list)
puts "*poink!*"
critter_list << self.clone
end
end
class Mutated_Kitty < Cat
include Asexual_Critter # inane example I know, but functional...
end
Просто помните, что если вы хотите играть с этим не делать:
critters = [Mutated_Kitty.new]
begin
critters.each { |c| c.reproduce(critters) }
end while critters.length > 0
Или вы будете в течение долгого ожидания, пока вы бежите из памяти, или, возможно, выдаёт ошибку сегментации.
Прошу прощения, если я понимаю ваш вопрос неправильно, но google «ruby dsl», вы можете найти эту вещь очень полезной для своей проблемы. также проверьте вопросы, заданные здесь.
проверить эту статью, если и не знаю, как начать:
[http://www.jroller.com/rolsen/entry/building_a_dsl_in_ruby][1]
я сделал что-то подобное раньше, сохранив изменения, которые я сделал в текстовый файл, и читать этот файл снова, когда программа перезапустила или перезагрузила свои настройки.
- 1. Правильный способ расширения класса Ruby?
- 2. Методы расширения для расширения класса?
- 3. Кодировка сообщения исключения расширения расширения Ruby C
- 4. Какова наилучшая практика для расширения класса в Ruby?
- 5. Расширение объекта класса Ruby
- 6. метод расширения для расширения статического класса
- 7. Расширения Android класса приложений
- 8. Ошибка расширения класса GearmanClient
- 9. Где реализация расширения класса?
- 10. Расширения PHP-класса
- 11. Ивара против расширения класса
- 12. java.lang.VerifyError после расширения класса
- 13. Java типа расширения класса
- 14. log4j2 расширения Logger класса
- 15. Расширения класса Objective-C
- 16. Как работает синтаксис расширения ruby?
- 17. Где разместить расширения ruby object
- 18. Метод класса класса Ruby Методы наследования
- 19. высшего класса уровень расширения внутреннего класса
- 20. Создание расширения класса для личных методов класса
- 21. Переменные класса класса Ruby легко
- 22. Переменная экземпляра класса Ruby класса
- 23. расширения класса (player.STR к player.Stats.STR)
- 24. Разделите значения от расширения класса
- 25. метод расширения для родового класса
- 26. Swift и использование расширения класса
- 27. Родная поддержка для расширения класса?
- 28. Проблема при попытке расширения класса
- 29. Объединение расширения класса с рекурсией
- 30. Создание класса путем расширения DefaultMessage
Не можете ли вы вообще оставить список аргументов из супервызов? Супер должен использовать те же аргументы, что и текущий метод, если вы не дадите ему что-то еще. Но Class.new звучит точно так, что ищет Дэвид. – Chuck
Вы можете в обычном определении, но не в 'define_method', это' Runtime Error: неявная передача аргумента super из метода, определяемого define_method(), не поддерживается. Указать все аргументы явно. Если davidk01 всегда переопределяет один и тот же метод, тогда будет работать обычный синтаксис 'def meth ... end'. – rampion