Псевдо-ООП в BASH

Jan 19, 2015 14:22

Давеча наткнулся на весьма интересную реализацию псевдо-ООП на баше. Идея вельми остроумна, но чуть-чуть погоняв ее, возникла мысль - а почему бы не посовершенствовать ее (Подразумевается, что вышеуказанная статья уже прочитанна, и понята). Итак: Для начала совершенно непонятно на кой ляд автору понадобились отдельные файлы obj.h и obj.class (для большего уподобления разве что?). Тайна сия велика есть, посему попробуем обойтись без них:
######################################################################## #/bin/bash obj() { . <(sed "s/obj/$1/g" <<< ' obj_properties=() # properties IDs fileName=0 fileSize=1 obj.method1(){ echo obj method1 called } obj.property(){ if [ "$2" == "=" ] then obj_properties[$1]=$3 else echo ${obj_properties[$1]} fi } obj.fileName(){ if [ "$1" == "=" ] then obj.property fileName = $2 else obj.property fileName fi } ') } obj myobj1 obj myobj2 ######################################################################## Проверяем в дебаггере
######################################################################## [13:04] bash -x oop.sh + obj myobj1 + . /dev/fd/63 ++ sed s/obj/myobj1/g ++ myobj1_properties=() ++ fileName=0 ++ fileSize=1 + obj myobj2 + . /dev/fd/63 ++ sed s/obj/myobj2/g ++ myobj2_properties=() ++ fileName=0 ++ fileSize=1 ######################################################################## Вуаля, работает. Только вспомним строки из исходной статьи: "Тут есть один момент: для разных классов нельзя использовать разные значения индексов со свойствами, имеющими одинаковые названия, поскольку это может привести к некорректной работе скрипта.". Так почему бы нам не сделать уникальные "properties IDs" для каждого псевдо-класса, тем паче все равно перед инклюдом мы sedом меняем "obj" на имя псевдо-класса. Да и обьявлять их заново при создании каждого обьекта нужды особой нет. Итак версия 2, дополненная:
######################################################################## #/bin/bash our_class_name() { . <(sed "s/obj/$1/g" <<< ' obj_properties=() # properties IDs if [[ ! "$our_class_name_IDs" ]]; then our_class_name_IDs=1 our_class_name_fileName=0 our_class_name_fileSize=1 fi obj.method1(){ echo obj method1 called } obj.property(){ if [ "$2" == "=" ] then obj_properties[$1]=$3 else echo ${obj_properties[$1]} fi } obj.fileName(){ if [ "$1" == "=" ] then obj.property our_class_name_fileName = $2 else obj.property our_class_name_fileName fi } ') } our_class_name myobj1 our_class_name myobj2 ######################################################################## Выхлоп:
######################################################################## [13:14] bash -x oop.sh + our_class_name myobj1 + . /dev/fd/63 ++ sed s/obj/myobj1/g ++ myobj1_properties=() ++ [[ ! -n '' ]] ++ our_class_name_IDs=1 ++ our_class_name_fileName=0 ++ our_class_name_fileSize=1 + our_class_name myobj2 + . /dev/fd/63 ++ sed s/obj/myobj2/g ++ myobj2_properties=() ++ [[ ! -n 1 ]] ######################################################################## Вуаля. Переменные обьявляются один раз и можно не беспокоиться на тему одинаковых названий свойств. А теперь попробуем методы:
######################################################################## # добавим в конец скрипта myobj1.fileName = "FirstName" myobj2.fileName = "Long name of 2nd object" myobj1.fileName myobj2.fileName ######################################################################## Выхлоп:
######################################################################## [13:22] bash oop.sh FirstName Long ######################################################################## О-па! За кулисами что-то пошло не так. А если использовать не "", а ''?
######################################################################## [13:22] bash oop.sh FirstName Long ######################################################################## Безрезультатно. А вампир то зарыт в незакавыченных $1, $2 и так далее. Версия третья исправленная:
######################################################################## #/bin/bash our_class_name() { . <(sed "s/obj/$1/g" <<< ' obj_properties=() # properties IDs if [[ ! "$our_class_name_IDs" ]]; then our_class_name_IDs=1 our_class_name_fileName=0 our_class_name_fileSize=1 fi obj.method1(){ echo "obj method1 called" } obj.property(){ if [ "$2" == "=" ] then obj_properties["$1"]="$3" else echo "${obj_properties["$1"]}" fi } obj.fileName(){ if [ "$1" == "=" ] then obj.property our_class_name_fileName = "$2" else obj.property our_class_name_fileName fi } ') } our_class_name myobj1 our_class_name myobj2 our_class_name myobj3 myobj1.fileName = 'FirstName' myobj2.fileName = 'Long name of 2nd object' myobj3.fileName = "Long name of 3rd object" myobj1.fileName myobj2.fileName myobj3.fileName ######################################################################## Выхлоп:
######################################################################## [13:31] bash oop.sh FirstName Long name of 2nd object Long name of 3rd object ######################################################################## [13:31] bash -x oop.sh + our_class_name myobj1 + . /dev/fd/63 ++ sed s/obj/myobj1/g ++ myobj1_properties=() ++ [[ ! -n '' ]] ++ our_class_name_IDs=1 ++ our_class_name_fileName=0 ++ our_class_name_fileSize=1 + our_class_name myobj2 + . /dev/fd/63 ++ sed s/obj/myobj2/g ++ myobj2_properties=() ++ [[ ! -n 1 ]] + our_class_name myobj3 + . /dev/fd/63 ++ sed s/obj/myobj3/g ++ myobj3_properties=() ++ [[ ! -n 1 ]] + myobj1.fileName = FirstName + '[' = == = ']' + myobj1.property our_class_name_fileName = FirstName + '[' = == = ']' + myobj1_properties["$1"]=FirstName + myobj2.fileName = 'Long name of 2nd object' + '[' = == = ']' + myobj2.property our_class_name_fileName = 'Long name of 2nd object' + '[' = == = ']' + myobj2_properties["$1"]='Long name of 2nd object' + myobj3.fileName = 'Long name of 3rd object' + '[' = == = ']' + myobj3.property our_class_name_fileName = 'Long name of 3rd object' + '[' = == = ']' + myobj3_properties["$1"]='Long name of 3rd object' + myobj1.fileName + '[' '' == = ']' + myobj1.property our_class_name_fileName + '[' '' == = ']' + echo FirstName FirstName + myobj2.fileName + '[' '' == = ']' + myobj2.property our_class_name_fileName + '[' '' == = ']' + echo 'Long name of 2nd object' Long name of 2nd object + myobj3.fileName + '[' '' == = ']' + myobj3.property our_class_name_fileName + '[' '' == = ']' + echo 'Long name of 3rd object' Long name of 3rd object ######################################################################## Вот это уже на что-то похоже. И работает с обоими типами кавычек. С sedом кстати тоже есть некая подлянка - не приведи Кришна в тексте псевдо-класса будет что-то типа 'obj' (например переменная $objective) - sed переименует ее в имя обьекта, и в результате н-ное количество веселья с переменной $myobj1ective гарантировано. Посему лучше все-таки длинное имя с претензией на уникальность:
######################################################################## #/bin/bash our_class_name() { . <(sed "s/our_object_name/$1/g" <<< ' our_object_name_properties=() # properties IDs if [[ ! "$our_class_name_IDs" ]]; then our_class_name_IDs=1 our_class_name_fileName=0 our_class_name_fileSize=1 fi our_object_name.method1(){ echo "our_object_name method1 called" } our_object_name.property(){ if [ "$2" == "=" ] then our_object_name_properties["$1"]="$3" else echo "${our_object_name_properties["$1"]}" fi } our_object_name.fileName(){ if [ "$1" == "=" ] then our_object_name.property our_class_name_fileName = "$2" else our_object_name.property our_class_name_fileName fi } ') } our_class_name myobj1 our_class_name myobj2 our_class_name myobj3 myobj1.fileName = 'FirstName' myobj2.fileName = 'Long name of 2nd object' myobj3.fileName = "Long name of 3rd object" myobj1.fileName myobj2.fileName myobj3.fileName ######################################################################## Тоже, конечно, не панацея, но встретить переменную в имени которой есть 'our_object_name' сильно сложнее чем с 'obj'. На всякий пожарный уточним - то что перед практическим использованием "our_class_name" меняется на имя класса, подразумевается. Продолжение тут

bash

Previous post Next post
Up