2. Совместимость
Эта глава расскажет о том, как удобнее всего создавать свои скрипты совместимыми со скриптами других людей. Если же вы отрицаете возможность, что помимо ваших в игре будут и чужие скрипты, то никто просто не станет пользоваться вашими работами. Например, если у пользователя может оказаться три отличных скрипта от других авторов, причём работающих вместе, и один ваш, который с ними не уживается, то естественно он выкинет ваше творение и предпочтёт использовать только те три. Другая причина, по которой стоит уделить внимание совместимости, тоже важна. Это экономия времени и собственных усилий. Если вы публикуете собственные скрипты, то рано или поздно какой-нибудь пользователь обязательно попросит переделать код так, чтобы он стал совместим с чьим-то другим.
Если ваш скрипт настраиваемый и в нём устанавливаются какие-то параметры, то с самого начала хорошо бы выставить их по умолчанию, для тех пользователей, которые не читают инструкции. Также будет замечательно, если ваши скрипты работают по системе Plug ‘n’ Play, т.е. так, что для полноценной работы их нужно лишь скопировать в редактор.
2.1. Псевдонимы
Под псевдонимами понимается создание своеобразных копий существующих методов. Для этого в RGSS используется зарезервированное слово alias.
Код:alias not_for_underaged alcohol
Эта строка создаёт псевдоним not_for_underaged для метода alcohol. Теперь экземпляр вашего класса свободно может вызывать метод alcohol через его псевдоним not_for_underaged.
Код:child.not_for_underaged child.alcohol
Обе эти команды делают одно и то же. Конечно же, вы не ограничены лишь методами класса. Также существует одна особенность, которая интересна с точки зрения совместимости: даже если вы переопределите оригинальный метод, псевдоним будет исполнять первоначальный вариант, к которому он установлен.
Код:def alcohol loop do drink have_fun if enough or evening_over? break end end end # контрольная точка 1 alias not_for_underaged alcohol # контрольная точка 2 def alcohol not_for_underaged if promille > 2.5 hangover end end
Этот код делает следующее:
- определяет метод alcohol
- даёт alcohol псевдоним not_for_underaged
- переопределяет alcohol (not_for_underaged будет исполнять старый метод!)
- обратите внимание, как новый метод alcohol вызывает своё старое определение через not_for_underaged
Давайте более глубоко проанализируем этот код. Попробуем выполнить:
Код:child.alcohol child.not_for_underaged
Это приведёт к следующему:
- перед контрольной точкой 1
Код:# запуск alcohol loop do drink have_fun if enough or evening_over? break end end # ОШИБКА! Неопределённый метод not_for_underaged!
- перед контрольной точкой 2
Код:# запуск alcohol loop do drink have_fun if enough or evening_over? break end end # запуск not_for_underaged loop do drink have_fun if enough or evening_over? break end end
- полностью
Код:# запуск нового alcohol not_for_underaged # запуск not_for_underaged loop do drink have_fun if enough or evening_over? break end end # продолжаем выполнение alcohol if promille > 2.5 hangover end # запуск not_for_underaged loop do drink have_fun if enough or evening_over? break end end
Видите ли вы, почему это так полезно для совместимости? Ещё вы можете поместить в конец методов или в их начало какой-нибудь свой код. Конечно, если требуется по-другому обработать данные, нужно расписать всё более подробно.
Код:def alcohol loop do drink have_fun if enough or evening_over? break end end if promille > 2.5 hangover end end alias not_for_underaged alcohol def alcohol(age = 17) age < 18 ? go_home : not_for_underaged end
Изначально, вызывая alcohol всегда запускается go_home (без указания аргументов, где число 17 уже установлено по умолчанию переменной age и где далее проверяется что она менее 18, другими словами: вы не получите выпивку не сказав свой возраст). Вызов alcohol(18) в результате запустит старый код метода alcohol.
Имейте в виду, вы можете не только добавить свой код в конец или начало метода, но и переписать существующий, добавить условий или по-другому манипулировать им как пожелаете.
Из моего опыта я узнал, что нельзя задать псевдоним методу модуля, определённого конструкцией def self.нечто.
схема 2.1.1. – псевдонимы и изменение кода
Помните, что если вы дадите псевдоним методу, который уже определён в сверхклассе и впоследствии измените метод сверхкласса или его псевдоним, то получите конфликт между ними и некоторые части перестанут работать.
2.2. Продумайте всё заранее
Это не обязательно, но порою весьма полезно. Если вы используете несколько ваших методов в более чем одном скрипте, а им назначен одинаковый псевдоним, то пользователи автоматически получать ошибку Слишком глубокий уровень стека (см. подробности в разделе 2.4.). Чтобы избежать такого исхода, вы можете добавить глобальную переменную (например $my_script) и установить её в качестве условия во всех ваших скриптах и тогда она задействует определённую часть кода.
Код:# my_script def my_script do_something end if $my_extra_do_something != true alias do_something_more do_something def do_something do_this_and_that do_something_more end $my_extra_do_something = true end # my_2nd_script def my_2nd _script do_something_new do_something end if $my_extra_do_something != true alias do_something_more do_something def do_something do_this_and_that do_something_more end $my_extra_do_something = true end # my_3rd_script def my_3rd _script do_something do_it_again end if $my_extra_do_something != true alias do_something_more do_something def do_something do_this_and_that do_something_more end $my_extra_do_something = true end
Добавление псевдонима методу do_something происходит лишь один раз, независимо от расположения скриптов в редакторе. Также этот способ может помочь, если другие скриптеры используют ваш псевдоним. Если в каком-то скрипте методу уже причислен псевдоним, то новый создаваться не будет. Конечно, в результате у вас получится больше кода, чем требуется, но это также улучшит совместимость, если использовать всё с умом.
схема 2.2.1. – взаимодействие скриптов
2.3. Проблемы с названиями
Заголовок говорит сам за себя. При создании псевдонима вы должны обратить внимание на то, как вы его называете. Один из хороших образцов: оригинальноеназваниеметод а_вашеимя_названиевашегоск рипта. Или же вы можете выбрать свой, уникальный стиль. Лично я называю свои методы так: оригинальноеназваниеметод а_названиемоегоскрипта_later.
Также я сокращаю слово initialize до init, update до upd и dispose до disp, так как это самые частые методы, которым приходится давать псевдонимы (для примера обратитесь к любому моему скрипту).
Также хорошо, если имена не будут слишком длинными (как в SDK, где в образец наименования псевдонимов входят даты и названия классов), так как их не сложно будет отыскать и вероятность получить ошибку Слишком глубокий уровень стека уменьшится.
2.4. “Слишком глубокий уровень стека”
Для начала сообщу кое-что для тех, кто знаком с программированием на других языках: RGSS НЕ поддерживает рекурсию! Далее вы увидите хороший пример рекурсии в C/C++. Так выглядел бы обыкновенный код функции, вычисляющей факториал числа:
Код:int factorial(int x) { int i, result = 1; for (i = 2, i <= x, i++) { result *= i; } return result;
А так бы выглядела та же самая функция, но с применением рекурсии:
Код:int factorial(int x) { if (x <= 0) return 1; return x * factorial(x - 1); }
Рекурсия позволяет вызывать тот же самый метод снова и снова до тех пор, пока есть место в стеке (подробности в [IURL="http://rpgmaker.su/showthread.php/518-Создание-скриптов-на-RGSS-для-людей-со-средними-знаниями-и-экспертов?p=9622&viewfull=1#post9622"]главе 8[/IURL]). Вот та же самая функция, написанная на RGSS:
Код:def factorial(x = 1) result = 1 for i in 2...x result *= i end return result end
А так бы выглядел код, если бы RGSS поддерживал рекурсию:
Код:def factorial(x = 1) return 1 if x <= 0 return x * factorial(x - 1) end
Видели бы вы моё лицо, когда я узнал что RGSS её не поддерживает. А раз так, то появляется ошибка Слишком глубокий уровень стека. Примеры далее как раз вызывают такую ошибку:
Код:def method_1 method_1 end
Код:def method_1 method_2 end def method_2 method_3 end def method_3 method_1 end
Код:alias new_method_1 method_1 def method_1 method_2 end def method_2 new_method_1 end
Помните, что в рекурсивном коде ДОЛЖНО БЫТЬ условие для его сброса. Если же функция постоянно вызывает сама себя и не возвращает никаких данных, то ваша программа будет работать со сбоями. Я не учёл этот факт в трёх примерах выше, будьте внимательны.
2.5. RAM или CPU?
Пока что это всё. Вы получили основные сведения о том, как сделать ваш скрипт совместимым с чужими или же вашими собственными. Если вам что-то было не ясно, то обратитесь к руководствам по созданию псевдонимов. Работая над совместимостью скриптов старайтесь использовать оперативную память, а не CPU. Самое плохое, что может случится — это то, что у вас будет повторяться одна и та же часть кода в нескольких скриптах, что не так важно, если они слаженно работают вместе, иначе может случится так что в результате сокращения код вообще не будет выполняться.
[IURL="http://rpgmaker.su/showthread.php/518-Создание-скриптов-на-RGSS-для-людей-со-средними-знаниями-и-экспертов?p=9614&viewfull=1#post9614"]Вернуться к содержанию...[/IURL]
Социальные закладки