最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

OOP 的 shell

网站源码admin4浏览0评论

OOP 的 shell

用面向对象的风格写 shell,原文在这

简介

使用方法:

创建对象:new <class> <实例名> 参数...

使用对象:<实例名>.<方法名> 参数...

我感觉实现的不是太好,成员函数值都变成全局的了;不过我自己也没动力去改它。

代码语言:shell复制
# class definition
class Storpel
func Storpel
func setName
func setQuality
func print
var name
var quality

# class implementation
Storpel::Storpel() {
  setName "$1"
  setQuality "$2"
  if [ -z "$name" ]; then setName "Generic"; fi
  if [ -z "$quality" ]; then setQuality "Normal"; fi
}

Storpel::setName() { name="$1"; }
Storpel::setQuality() { quality="$1"; }
Storpel::print() { echo "$name ($quality)"; }

# usage
new Storpel one "Storpilator 1000" Medium
new Storpel two
new Storpel three

two.setName "Storpilator 2000"
two.setQuality "Strong"

one.print
two.print
three.print

echo ""

echo "one: $one ($(typeof $one))"
echo "two: $two ($(typeof $two))"
echo "three: $three ($(typeof $two))"

输出结果

代码语言:txt复制
Storpilator 1000 Medium (Normal)
Storpilator 2000 (Strong)
Generic (Normal)

one: c96fe5e519584e5c8c4d8a02f90e4419 (Storpel)
two: db55f2cf5025481c8c2d23330b2a0a07 (Storpel)

核心代码

代码语言:shell复制
#!/bin/bash

# ---------------------------------------------------------------------------
# OO support functions
# Kludged by Pim van Riezen <pi@madscience.nl>
# ---------------------------------------------------------------------------
DEFCLASS=""
CLASS=""
THIS=0

class() {
  DEFCLASS="$1"
  eval CLASS_${DEFCLASS}_VARS=""
  eval CLASS_${DEFCLASS}_FUNCTIONS=""
}

static() {
  return 0
}

func() {
  local varname="CLASS_${DEFCLASS}_FUNCTIONS"
  eval "$varname=\"\${$varname}$1 \""
}

var() {
  local varname="CLASS_${DEFCLASS}_VARS"
  eval $varname="\"\${$varname}$1 \""
}

loadvar() {
  eval "varlist=\"\$CLASS_${CLASS}_VARS\""
  for var in $varlist; do
    eval "$var=\"\$INSTANCE_${THIS}_$var\""
  done
}

loadfunc() {
  eval "funclist=\"\$CLASS_${CLASS}_FUNCTIONS\""
  for func in $funclist; do
    eval "${func}() { ${CLASS}::${func} \"\$*\"; return \$?; }"
  done
}

savevar() {
  eval "varlist=\"\$CLASS_${CLASS}_VARS\""
  for var in $varlist; do
    eval "INSTANCE_${THIS}_$var=\"\$$var\""
  done
}

typeof() {
  eval echo \$TYPEOF_$1
}

new() {
  local class="$1"
  local cvar="$2"
  shift
  shift
  local id=$(uuidgen | tr A-F a-f | sed -e "s/-//g")
  eval TYPEOF_${id}=$class
  eval $cvar=$id
  local funclist
  eval "funclist=\"\$CLASS_${class}_FUNCTIONS\""
  for func in $funclist; do
    eval "${cvar}.${func}() { local t=\$THIS; THIS=$id; local c=\$CLASS; CLASS=$class; loadvar; loadfunc; ${class}::${func} \"\$*\"; rt=\$?; savevar; CLASS=\$c; THIS=\$t; return $rt; }"
  done
  eval "${cvar}.${class} \"\$*\" || true"
}

代码解释

看了半天,看的我晕头转向,记录几个自己不熟的点:

为什么用 eval 来定义 varlist/funclist:

是为了处理间接变量的引用,因为 shell 没法嵌套使用变量,比如:${${a}} 是不行的

比如处理 \$CLASS_${class}_FUNCTIONS 时,需要先拼接变量名,再求值,但是用 eval 可以方便的做到这一点;

for ... in 一个空白分开的字符串在 zsh 中不支持

除非做一些设置;最好还是放到数组里再遍历

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论