Не нашел такой темы, а тема важная, для мейкера. Для скриптеров со стажем это наверное будет не очень интересно.
И так, что такое alias - в руби это просто напросто ссылка на метод, когда вы хотите чтобы ваш метод отзывался и на другое (третье, четвертое...) имя.
class Fireblast
def damage
100
end
alias dmg damage
end
spell = Fireblast.new
spell.damage #=> 100
spell.dng #=> 100
Алиасы можно объявить при помощи alias и alias_method. Первый является ключевым словом, и может принимать в себя имена методов как есть (не строки и не символы, а просто имена), второй - приватный метод объектов Class / Module, он принимает строки \ символы, разделенные запятыми (как обычный метод).
В обоих случаях
первым следует передовать имя нового метода, вторым - имя оригинала.
class Fireblast
def cast_time
1
end
alias_method :delay, :cast_time
end
Допустим есть у вас в мейкере класс Fireblast, допустим вы хотите внести в его изменения: хотите чтобы он кроме урона делал еще что нибудь (выводил сообщение на STDOUT для примера.) Как это сделать? Первый способ - и самый плохой по совместительству - это найти этот класс \ метода и все исправить на месте. Если будете так делать в итоге что нибудь сломаете в оригинальных скриптах и будете долго думать, как все починить. Второй - использовать возможность руби переопределять код налету, и написать в новом скрипте (сделать патч) как-нибудь так:
class Fireblast
def damage
puts 'Fireblast#damage called'
100
end
end
Это будет работать, но вы только что сделали дубликат кода - цифра 100 встречается в двух местах - в оригинальном методе, и в вашем патче. Это особо не страшно если вам нужно только одну строчку дублировать. А если их там с десяток? Тогда лучше использовать такую странную особенностью руби как alias chain. Суть в том, что когда вы делаете алиас при помощи alias (alias_method) руби на саом деле копирует метод, а не просто добавляет ссылку. Это неприятно на первый взгляд, зато позволяет делать так:
class Fireblast
alias original_cast_time cast_time #мы сделали копию cast_time и назвали ее orignal_cast_time
def cast_time #переопределяем метод cast_time
puts "Fireblast#cast_time called" # добовляем новый функционал
original_cast_time # вызываем старый метод
end
end
spell = Fireblast.new
spell.cast_time #=> выведет на STDOUT сообщение и вернет 1
Многие скрипты, которые модифицируют методы оригинальных классов, делают это именно так.
Так же объясню как делать алиасы к методам модуля.
Модуль можно использовать двумя способами, первый способ - когда нужно подмешать (Mixin) методы в свой класс:
module Words
def bye
puts 'good bye'
end
end
class Test
include Words
end
Test.new.bye #выведет на STDOUT good bye
Допустим вы хотите сделать alias chain для этого модуля. Вы можете сделать это так же как и для классов:
module Words
alias original_bye bye
def bye
puts "I say you"
original_bye
end
end
Test.new.bye #выведет два сообщения на STDOUT
Но гораздо лучше использовать стандартное наследование:
class Test
include Words
def bye
puts "I say you"
super #это работает как для классов, так и для модулей, подключенных через include
end
end
Tew.new.bye #выведет все так же две строки на STDOUT
Так же модуль можно использовать как контейнер для функций (у меня ниразу не было надобности использовать модули так, я всегда находил повод сделать класс)
module Words
def self.greetings
puts 'hello'
end
end
Words.greetings #выведет hello на STDOUT
И когда вы хотите сделать alias chain для такой функции начинаются интересные дела. Есть несколько способов это сделать, больше всего мне нравится такой:
module Words
instance_eval do
alias original_greetings greetings
def greetings
puts 'I say you'
original_greetings
end
end
end
Words.greetings #выведет 2 строки на STDOUT
Что такое instance_eval я обязательно расскажу, когда буду говорить о метапрограммировании.
Тут информация о том как это
нужно делать в руби 2.1.2. Алиасы там все еще работают так же, как и в ранних версиях, но появился путь, значительно более прозрачный.
module FireblastPatch #сделаем модуль, где переопределим метод damage
def damage
puts "I added this line with module" #добавим этот функционал
super #вызовем оригинальный метод
end
end
Fireblast.prepend FireblastPatch #новый метод prepend добовляет методы модуля в класс
#и руби будет искать метод сначала тут, потом уже в классе