Цепочка методов — очень удобный метод для одновременного вызова нескольких методов. Это не только улучшает читабельность кода, но и уменьшает объем кода, необходимого при взаимодействии с классом или экземпляром класса.
Возможно, вы уже так или иначе взаимодействовали с цепочкой методов, особенно если вы использовали ActiveRecord. Помните, что вы делали что-то вроде этого Model.where(…).order(…)
Да, это метод цепочки. В этой статье вы узнаете, как применять те же функции в своем собственном коде.
Эта статья будет разделена на две простые части:
- Введение в метод цепочки
- Метод цепочки на уровне класса
Первая часть будет охватывать основы цепочки методов, с пошаговыми примерами; а во второй части будет объяснено, как выполнить цепочку методов на уровне класса, будь то с помощью явного объявления метода методов класса или с помощью и расширения дополнительного модуля.
Вы готовы отправиться в это удивительное путешествие? Пошли!
Введение в метод цепочки
Для вводной части мы собираемся разработать класс, который будет содержать несколько методов, которые в конечном итоге могут быть объединены в цепочку, и один метод, который выводит сообщение. Давайте начнем с нашей базовой структуры классов:
class Person
def name(value)
end
def age(value)
end
def introduce
end
end
Ничего особенного, но это послужит основой для этого примера. Как видите, он содержит три метода: name()
age()
introduce
Имея эту основную информацию под рукой, давайте осуществим следующий шаг.
Теперь мы собираемся сохранить входные значения для name()
age()
# ...
def name(value)
@name = value
end
def age(value)
@age = value
end
# ...
Отлично, с этим дополнением к нашим методам, давайте попробуем цепочку методов и посмотрим, что произойдет:
> person = Person.new
# => #<Person:0x007fb18ba29cb8>
> person.name('Baz')
# => "Baz"
> person.name('Baz').age(21)
NoMethodError: undefined method `age' for "Baz":String
Как и следовало ожидать, это не работает. Причина в том, что методы просто возвращают значение — в данном случае строку. Нам нужно изменить наши методы еще раз, и на этот раз мы собираемся вернуть что-то еще: self
Возвращая self
Полегче, да ?! Хорошо, пришло время снова изменить наши методы:
# ...
def name(value)
@name = value
self
end
def age(value)
@age = value
self
end
# ...
Фантастика, что произойдет, если мы попытаемся связать наши вызовы методов?
> person = Person.new
# => #<Person:0x007ff202829e38>
> person.name('Baz')
# => #<Person:0x007ff202829e38 @name="Baz">
> person.name('Baz').age(21)
# => #<Person:0x007ff202829e38 @name="Baz", @age=21>
Это сработало! Поздравляем, вы только что внедрили цепочку методов в Ruby! Теперь нам нужно изменить наш метод introduce
# ...
def introduce
puts "Hello, my name is #{@name}, and I am #{@age} years old."
end
# ...
Как вы думаете, что произойдет, когда весь наш код будет на месте, когда мы вызовем introduce
> person = Person.new
# => #<Person:0x007fd079085ba0>
> person.name('Baz').age(21).introduce
# => Hello, my name is Baz and I am 21 years old.
Да, это сработало, как и ожидалось. Обратите внимание, что метод introduce
self
Вот полный код для этого примера, который я также внес в Википедию в статье, посвященной методам :
class Person
def name(value)
@name = value
self
end
def age(value)
@age = value
self
end
def introduce
puts "Hello, my name is #{@name} and I am #{@age} years old."
end
end
В качестве упражнения для читателя я призываю вас изменить метод introduce
Например, если доступен только @name
Если доступен только @age
Цепочка методов на уровне класса
Мы только что узнали, как связывать вызовы наших методов при вызове методов для экземпляра класса. Но как насчет объединения методов на уровне класса, аналогично Model.where(…).order(…)
Это почти тот же процесс, за исключением того, что объявление нашего метода будет на уровне класса, а не на уровне экземпляра.
Давайте продолжим и сделаем это, давайте разработаем класс, который содержит методы класса, которые могут быть объединены в цепочку. Базовая структура для этого примера будет выглядеть примерно так:
class Speaker
class << self
def say(what)
@say = what
self
end
def drink(what)
@drink = what
self
end
def output
"The speaker drinks #{@drink} and says #{@say}"
end
end
end
Довольно просто, правда? Обратите внимание, что все эти три метода являются методами класса. Я мог бы объявить их по отдельности с помощью def self.say()…
class << self
Отлично, давайте поиграем с этим сейчас:
> Speaker.say('hello').drink('water').output
# => The speaker drinks water and says hello
И вот он у вас, работал как шарм.
Еще один способ сделать это без явного объявления методов класса — использовать модуль и extend
Делая это, мы выставляем методы в модуле как методы класса в нашем классе Speaker
module SpeakerClassMethods
def say(what)
@say = what
self
end
def drink(what)
@drink = what
self
end
def output
"The speaker drinks #{@drink} and says #{@say}"
end
end
class Speaker
extend SpeakerClassMethods
end
И он должен работать точно так же, как явно объявив методы класса:
> Speaker.say('hello').drink('water').output
# => The speaker drinks water and says hello
Отлично, это сработало. В качестве другого упражнения для читателя я призываю вас изменить метод output
Вывод
Эта статья продемонстрировала, как просто и легко включить цепочку методов в Ruby, будь то на уровне экземпляра или на уровне класса. Он также показал различные способы достижения одних и тех же результатов, используя разные методы при добавлении цепочки методов уровня класса. И я надеюсь, что он предоставил вам достаточно информации, чтобы вы могли применять те же методы к своему собственному коду.