Метапрограммирование
Метапрограммирование
Метапрограммирование - это область программирования, в которой результатом написания кода является не потребительская программа, а изменение языка или и вовсе, создание нового. Звучит тяжело, но попробуем разобраться.
Как мв рассматривали ранее, в Ruby абсолютно все является объектами и классами. например наш кастомный класс Person
невидимо для нас является наследником Object
, при этом класс Person
является объектом класса Class
. Именно с последней особенностью тестно связаны наши методы класса, которые мы обявляет через self
.
Для начала давайте разберем такое понятие как singleton
методы.
Предположим у нас есть класс Person
class Person
def hello
puts 'Hello'
end
end
А теперь посмотрим как мы можем добавить новый метод для объекта не изменяя сам класс
person_1 = Person.new
person_2 = Person.new
person_1.hello # = Hello
person_2.hello # = Hello
person_1.bye # Ошибка, ведь такой метод не существует
person_2.bye # Ошибка, ведь такой метод не существует
# Мы создали новый singleton метод у объекта под названием bye
# Важно понимать, что этот метод существует только у данного объекта
def person_1.bye
puts 'Bye'
end
person_1.bye # Bye
person_2.bye # Ошибка, ведь такой метод не существует
Так вот, когда вы объявляете метод класса с помощью self
в начале, то вы по сути создаете singletone метод для объекта класса Class
, ведь наш класс Person
вляется его объектом.
Само по себе ключевое слово self
обозначает указание на собственный объект, только в зависимости от области нахождения этого слова, может меняться сам оюъект на который он указывает, т.е. в нашем случае это либо указание на собственный объект класса Person
, либо указание на объект класса Class
.
Аналогичную запись можно сделать с помощью наследования
person_1 = Person.new
person_2 = Person.new
person_1.hello # = Hello
person_2.hello # = Hello
person_1.bye # Ошибка, ведь такой метод не существует
person_2.bye # Ошибка, ведь такой метод не существует
# Мы создали новый singleton метод у объекта под названием bye
# Важно понимать, что этот метод существует только у данного объекта
def person_1.bye
puts 'Bye'
end
class << person_2
def world
puts 'World'
end
end
person_1.bye # Bye
person_2.bye # Ошибка, ведь такой метод не существует
person_1.world # Ошибка, ведь такой метод не существует
person_2.world # World
Кроме того, мы может добавлять на лету методы для нашего класса
def Person.example
puts 'Example'
end
class << Person
def another_example
puts 'Another example'
end
end
Person.example # Example
Person.another_example # Another example
Помимо прочего, мы также можем расширять методы класса с помощью специального метода instance_eval
# Внутри этого блока кода мы можем создавать новые методы для нашего класса
Person.instance_eval do
def fly
puts 'Person is flying'
end
end
Person.fly # Person is flying
А также может добавлять методы для каждого объекта нашего лкасса с помощью метода class_eval
# Методы объявленные в этом блоке будут принадлежать всем объектам
Person.class_eval do
def toilet
puts "Person is going to toilet"
end
end
person_3 = Person.new
person_4 = Person.new
person_3.toilet # Person is going to toilet
person_4.toilet # Person is going to toilet
В Ruby существует оргомное количество библиотек, которые расширяют те или иные классы. Фреймворк Rails по большей части строится вокруг этой концепции, с чем вы убедитесь позже.
Задание reverse_words
Напишите метод reverse_words
, который можно будет вызвать у любой строки и который будет менять последовательность слов в обратном порядке
Пример:
words = "Hello World"
reverse = worlds.reverse_words # = "Word Hello"
Дополнительный материал:
Last updated