Метапрограммирование

Метапрограммирование

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

Как мв рассматривали ранее, в 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