आपको बाश में कक्षाओं या वस्तुओं को लागू करने के लिए बहुत अधिक bash कोड की आवश्यकता नहीं है।
कहो, 100 लाइनें।
बैश में साहचर्य सरणियां हैं जिनका उपयोग विरासत, विधियों और गुणों के साथ एक साधारण वस्तु प्रणाली को लागू करने के लिए किया जा सकता है।
तो, आप इस तरह एक वर्ग को परिभाषित कर सकते हैं:
class Queue N=10 add=q_add remove=q_remove
इस कतार का एक उदाहरण इस तरह किया जा सकता है:
class Q:Queue N=100
या
inst Q:Queue N=100
चूंकि कक्षाएं एक सरणी के साथ कार्यान्वित की जाती हैं, इसलिए कक्षा और आवृत्ति वास्तव में समानार्थक शब्द हैं - जैसे जावास्क्रिप्ट में।
इस कतार में आइटम जोड़ना इस तरह किया जा सकता है:
$Q add 1 2 aaa bbb "a string"
किसी चर X में आइटम निकालना इस तरह किया जा सकता है:
$Q remove X
और किसी वस्तु की डंपिंग संरचना इस तरह की जा सकती है:
$Q dump
जो कुछ इस तरह लौटेगा:
Q {
parent=Queue {
parent=ROOT {
this=ROOT
0=dispatch ROOT
}
class=Queue
N=10
add=q_add
remove=q_remove
0=dispatch Queue
}
class=Q
N=4
add=q_add
remove=q_remove
0=dispatch Q
1=
2=ccc ddd
3=
4=
}
इस तरह एक वर्ग समारोह का उपयोग कर कक्षाएं बनाई जाती हैं:
class(){
local _name="$1:" # append a : to handle case of class with no parent
printf "$FUNCNAME: %s\n" $_name
local _this _parent _p _key _val _members
_this=${_name%%:*} # get class name
_parent=${_name#*:} # get parent class name
_parent=${_parent/:/} # remove handy :
declare -g -A $_this # make class storage
[[ -n $_parent ]] && { # copy parent class members into this class
eval _members=\"\${!$_parent[*]}\" # get indices of members
for _key in $_members; do # inherit members from parent
eval _val=\"\${$_parent[$_key]}\" # get parent value
eval $_this[$_key]=\"$_val\" # set this member
done
}
shift 1
# overwrite with specific values for this object
ROOT_set $_this "$@" "0=dispatch $_this" "parent=${_parent:-ROOT}" "class=$_this"
}
नोट: जब एक नए वर्ग या उदाहरण को परिभाषित करते हैं, तो आप किसी भी सदस्य मान या फ़ंक्शन को ओवरराइड कर सकते हैं।
बैश सहयोगी सरणियों में एक विचित्रता है जो इस काम को बड़े करीने से करती है: $ Q [0]} $ Q के समान है। इसका मतलब है कि हम विधि प्रेषण समारोह को कॉल करने के लिए सरणी नाम का उपयोग कर सकते हैं:
dispatch(){
local _this=$1 _method=$2 _fn
shift 2
_fn="$_this[$_method]" # reference to method name
${!_fn} $_this "$@"
}
एक पक्ष यह है कि मैं डेटा के लिए [0] का उपयोग नहीं कर सकता हूं इसलिए मेरी कतारें (इस मामले में) सूचकांक = 1 से शुरू होती हैं। वैकल्पिक रूप से मैं "q + 0" जैसे सहयोगी सूचकांकों का उपयोग कर सकता था।
सदस्यों को पाने और सेट करने के लिए आप कुछ इस तरह से कर सकते हैं:
# basic set and get for key-value members
ROOT_set(){ # $QOBJ set key=value
local _this=$1 _exp _key _val
shift
for _exp in "$@"; do
_key=${_exp%%=*}
_val="${_exp#*=}"
eval $_this[$_key]=\"$_val\"
done
}
ROOT_get(){ # $QOBJ get var=key
local _this=$1 _exp _var _key
shift
for _exp in "$@"; do
_var=${_exp%%=*}
_key=${_exp#*=}
eval $_var=\"\${$_this[$_key]}\"
done
}
और एक वस्तु संरचना को डंप करने के लिए , मैंने इसे बनाया:
नोट: यह BOP में OOP के लिए आवश्यक नहीं है, लेकिन यह देखना अच्छा है कि ऑब्जेक्ट कैसे बनाए जाते हैं।
# dump any object
obj_dump(){ # obj_dump <object/class name>
local _this=$1 _j _val _key; local -i _tab=${2:-(${#_this}+2)} # add 2 for " {"
_tab+=2 # hanging indent from {
printf "%s {\n" $_this
eval "_key=\"\${!$_this[*]}\""
for _j in $_key; do # print all members
eval "_val=\"\${$_this[\$_j]}\""
case $_j in
# special treatment for parent
parent) printf "%*s%s=" $_tab "" $_j; ${!_val} dump $(( _tab+${#_j}+${#_val}+2 ));;
*) printf "%*s%s=%s\n" $_tab "" $_j "$_val";;
esac
done
(( _tab-=2 ))
printf "%*s}\n" $_tab ""
return 0
}
मेरे ओओपी डिज़ाइन ने वस्तुओं के भीतर वस्तुओं पर विचार नहीं किया है - विरासत में मिला वर्ग को छोड़कर। आप उन्हें अलग से बना सकते हैं, या वर्ग () की तरह एक विशेष निर्माता बना सकते हैं। * obj_dump * आंतरिक कक्षाओं का पता लगाने के लिए उन्हें पुन: मुद्रित करने के लिए संशोधित करने की आवश्यकता होगी।
ओह! और मैं क्लास फंक्शन को सरल बनाने के लिए मैन्युअल रूप से एक ROOT क्लास परिभाषित करता हूं :
declare -gA ROOT=( \
[this]=ROOT \
[0]="dispatch ROOT" \
[dump]=obj_dump \
[set]="ROOT_set" \
[get]="ROOT_get" \
)
कुछ कतार कार्यों के साथ मैंने कुछ वर्गों को इस तरह परिभाषित किया:
class Queue \
in=0 out=0 N=10 \
dump=obj_dump \
add=q_add \
empty=q_empty \
full=q_full \
peek=q_peek \
remove=q_remove
class RoughQueue:Queue \
N=100 \
shove=q_shove \
head_drop=q_head_drop
कुछ कतार उदाहरण बनाए और उन्हें काम दिया:
class Q:Queue N=1000
$Q add aaa bbb "ccc ddd"
$Q peek X
$Q remove X
printf "X=%s\n" "$X"
$Q remove X
printf "X=%s\n" "$X"
$Q remove X
printf "X=%s\n" "$X"
class R:RoughQueue N=3
$R shove aa bb cc dd ee ff gg hh ii jj
$R dump