В Ruby используются методы генерации методов везде.
Например, существуют способы получения инкубационных и геттер методы:
class Module
def attr_reader(*attributes)
attributes.each do |attribute|
define_method(attribute) do instance_variable_get(:"@#{attribute}") end
end
end
def attr_writer(*attributes)
attributes.each do |attribute|
define_method(:"#{attribute}=") do |value|
instance_variable_set(:"@#{attribute}", value)
end
end
end
def attr_accessor(*attributes)
attr_reader(*attributes)
attr_writer(*attributes)
end
end
Когда слово один из этих методов, как это:
attr_reader :bla
Это создаст метод, названный bla
, который возвращает значение переменной экземпляра с именем @bla
.
И
attr_writer :bla
сгенерирует метод, названный bla=
(присвоение имен метода с знаком равенства в конце концов, это обычное соглашение об именах для сеттеров в Ruby), который присваивает свой аргумент в переменный экземпляре с именем @bla
.
class Foo
attr_reader :foo, :bar
attr_writer :baz, :quux
attr_accessor :gargle, :blarf
end
Это будет генерировать методы foo
, bar
, baz=
, quux=
, gargle
, gargle=
, blarf
, blarf=
.
Другим примером является ORM-библиотека ActiveRecord
для Ruby, которая генерирует методы getter и setter, а также методы поиска для моделей, основанные на отражении по схеме базы данных во время выполнения.
ActiveRecord
также имеет методы динамического поиска, которые позволяют вам делать что-то вроде Person.find_by_name_and_age('John', 42)
. Конечно, существует бесконечно много комбинаций столбцов базы данных, которые можно было бы искать, поэтому нецелесообразно создавать все методы заранее. Вместо этого ActiveRecord
устанавливает привязку method_missing
для перехвата вызовов к несуществующим методам, начиная с find_by_
. Однако, как только он перехватил вызов метода, он генерирует метод этого имени в предположении, что метод может быть вызван чаще всего за это время, и, таким образом, динамический перехват может быть подвергнут второстепенному.
Вообще говоря, это код Синтез полезен везде, где Генерация кода полезно, но со значительным преимуществом, что
- не загромождать исходного дерева, потому что все это порождало «код "является эфемерным
- Вы используете собственные возможности языков для генерации кода, поэтому он будет (в некотором смысле) всегда корректным, тогда как при генерации кода (простого текстового) вам придется позаботиться о создании синтаксически допустимого кода
По моему опыту, это в основном для конкретных вещей. Подумайте о библиотеках сериализации, которые генерируют код сериализации с использованием отражения и IL-излучения, поэтому вам не нужно писать и поддерживать этот код вручную. Выражения полезны для перевода кода, например, в SQL-запросы. Однако Monkeypatching позволяет вам заменять/отменять существующие функции, что может привести к большой путанице. Выглядит полезно при написании тестового кода. –