Bash'te sınıfları veya nesneleri uygulamak için çok fazla bash koduna ihtiyacınız yoktur.
100 çizgi söyle.
Bash, kalıtım, yöntemler ve özelliklerle basit bir Object sistemini uygulamak için kullanılabilecek ilişkisel dizilere sahiptir.
Yani, böyle bir sınıfı tanımlayabilirsiniz:
class Queue N=10 add=q_add remove=q_remove
Bu Kuyruğun bir örneğini oluşturmak şu şekilde yapılabilir:
class Q:Queue N=100
veya
inst Q:Queue N=100
Sınıflar bir dizi ile gerçekleştirildiğinden, sınıf ve inst gerçekten javascript'teki gibi eş anlamlıdır.
Bu kuyruğa eşya eklemek şu şekilde yapılabilir:
$Q add 1 2 aaa bbb "a string"
Öğeleri X değişkenine kaldırmak şu şekilde yapılabilir:
$Q remove X
Ve bir nesnenin damping yapısı şu şekilde yapılabilir:
$Q dump
Hangisi böyle bir şey döndürür:
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=
}
Sınıflar şunun gibi bir sınıf işlevi kullanılarak oluşturulur:
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"
}
NOT: Yeni bir sınıf veya örnek tanımlarken, herhangi bir üye değerini veya işlevi geçersiz kılabilirsiniz.
Bash ilişkisel dizilerinin bu çalışmayı düzgünce yapan bir tuhaflığı var: $ Q [0]} $ Q ile aynı. Bu, bir yöntem gönderme işlevini çağırmak için dizi adını kullanabileceğimiz anlamına gelir:
dispatch(){
local _this=$1 _method=$2 _fn
shift 2
_fn="$_this[$_method]" # reference to method name
${!_fn} $_this "$@"
}
Aşağı tarafı, veri için [0] kullanamıyorum, bu yüzden sıralarım (bu durumda) index = 1'den başlıyor. Alternatif olarak "q + 0" gibi birleştirici dizinler kullanabilirdim.
To almak ve ayarlamak üyeleri böyle bir şey yapabilir:
# 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
}
Ve bir nesne yapısını terk etmek için şunu yaptım:
Not: Bu bash OOP için gerekli değildir, ancak nesnelerin nasıl yapıldığını görmek güzel.
# 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
}
OOP tasarımım, devralınan sınıf dışında, nesnelerdeki nesneleri dikkate almadı. Bunları ayrı ayrı oluşturabilir veya class () gibi özel bir kurucu yapabilirsiniz. * obj_dump * içsel sınıfları tekrar tekrar basmak üzere tespit etmek için değiştirilmeliydi.
Ah! ve sınıf fonksiyonunu basitleştirmek için bir ROOT sınıfını manuel olarak tanımlarım :
declare -gA ROOT=( \
[this]=ROOT \
[0]="dispatch ROOT" \
[dump]=obj_dump \
[set]="ROOT_set" \
[get]="ROOT_get" \
)
Birkaç kuyruk fonksiyonuyla bunun gibi bazı sınıflar tanımladım:
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
Bazı Sıra örnekleri oluşturuldu ve çalışmalarını sağladı:
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