批处理面向对象

本文介绍了一个基于命名约定的批处理面向对象框架,实现了静态类、实例类、类继承、字段和方法。批处理类通过静态类创建对象并绑定方法,遵循特定的命名规则。以@Array类为例,详细解释了类的定义、方法绑定和对象初始化过程,包括数组操作方法如Push、Insert等。此外,还讨论了类的继承机制,派生类如何调用基类构造和析构函数,以及成员覆盖和基类方法调用。

这是一个基于命名的面向对象框架,实现静态类、实例类、类继承;字段、方法;私有、公有;


方法调用方式模仿高级面向对象语言,希望为你节省编码时间;使用时请务必遵守命名约定


批处理类定义约定:


1.(1)普通环境变量则不加任何前缀的正常命名;

  (2)普通标签函数以“#FunctionName”格式来命名;

  (3)普通标签函数内部临时变量以“_VarName”格式命名,注意是单下划线;

  (4)类以“@ClassName”格式命名;

  (5)类成员中标签函数成员以“ClassName.MethodName”格式命名;

  (6)类的所有标签函数临时变量以“__VarName”格式命名,注意是双下划线;
 
  (7)类创建的对象用“$ObjName”格式命名,请传递对象名时带“$”符号;

  (8)数组也被视为对象,故请以$ArrayName形式定义;

  (9)可作为一个外部调用单位的标签函数(如类函数成员标签函数与普通标签函数)内

      部如果还有标签函数,则以MainFuncName_SubFuncName的格式命名,其中

      MainFuncName是可作为外部调用主体的标签函数的标签名,这样可以有效的防止

      标签访问错误的出现。因为毕竟内部标签函数不是成员,所以不用“.”号。因为如果类

      库庞大,那么难免内部标签函数会出现冲突,所以用主标签函数的标签名作前缀

  (10)对象只有字段与方法,如果对象的字段也是一个对象,则这个字段请以如下格式

      命名:$ObjName.FieldName,即一个对象链上只出现一个“$”符号

  (11)类私有方法使用ClassName.__MethodName格式命名,私有方法不与对象绑定
    

3.数组的数组名$ArrayName.UBound保存数组的最大下标,$ArrayName[n](n为自

  然数)保存元素

4.为语法上的简洁及功能的强健计:

        (1)所有对象必须先创建,再才可以调用方法,不能一边创建一边调用

        (2)创建对象的语法是如下,这样可以传递足量参数,如果需要的话:

                Call :@<ClassName> $<ObjName> arg1 arg2 arg3 ...

        (3)调用对象方法的语法如下,这样可以传递足量参数,如果需要的话:

                Call :%$<ObjName>.<MethodName>% arg1 arg2 arg3 ...

        (4)读取对象属性或字段的语法为:

                $<ObjName>.<FieldName>

5.本来是要检查对象名合法性的,不过为了更高的效率,所以还是不要这一步,希望使用者

  严格遵照命名约定来命名对象;

6.所有实例类都必须有Del方法(删除对象,清除对象数据即方法绑定)、Str方法

  (简单地回显对象的字符串表示)、Type属性(简单的保存它所属的类型信息)成员

7.所有的方法如果需要使用返回值,就用$ObjName.MethodName.Return来返回,记得

  在方法开始执行时,清除上一次的调用结果

8.总是使用类临时变量__this来接收对象名

9.静态类创建一个与类同名的对象,并将对象与方法绑定,也提供Del方法


因为这是基于命名约定的框架,所以请务必遵照其中的命名约定,尤其是函数标签命名及对象命名


@Array类:提供数组所需的所有功能

   @Array:

        Type                 "@Array"

        ====                ==================

        Push                将一个元素添加到数组开头

        Insert                添加一个元素到数组指定位置

        Remove           删除指定索引位置上的元素

        Append            添加一个元素到数组尾部

        Extend              将另一个数组追加进原来的数组对象

        =====               ============================

        Reserve            反转数组

        Str                      回显数组的字符串表示

        Del                     删除对象数据,解除方法绑定


@Array以及@Array2的实现(其中@Array2继承自@Array):

[批处理面向对象.bat]

@Echo off&SetLocal EnableDelayedExpansion&Color a
Echo 0.创建一个数组$days,给它赋予周一到周五的工作日名称
Call :@Array "$days" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday"
Echo.
Call :%$days.Str%
Echo %$days.Str.Return%
Echo.
Echo 1.在数组$days开始位置压入一个元素"Sunday"
Call :%$days.Push% "Sunday"
Echo.
Call :%$days.Str%
Echo %$days.Str.Return%
Echo.
Echo 2.插入"Hello World"到数组$days的第3索引位置
Call :%$days.Insert% 3 "Hello World"
Echo.
Call :%$days.Str%
Echo %$days.Str.Return%
Echo.
Echo 3.删除数组$days的第3索引位置上的元素
Call :%$days.Remove% 3
Echo.
Call :%$days.Str%
Echo %$days.Str.Return%
Echo.
Echo 4.在数组$days的末尾位置追加一个元素"Saturday"
Call :%$days.Append% "Saturday"
Echo.
Call :%$days.Str%
Echo %$days.Str.Return%
Echo.
Echo 5.在数组$days的末尾追加另一个数组$Signs
Echo.
ECho 5.1创建数组$Signs,给它添加两个元素"+"、"-"
Echo.
Call :@Array "$Signs" "+" "-"
Echo 5.2回显数组$Signs的信息
Echo.
Call :%$Signs.Str%
Echo %$Signs.Str.Return%
Echo.
Echo 5.3将$Signs的所有元素追加到$days末尾
Call :%$days.Extend% "$Signs"
Echo.
Echo 5.4回显追加$Signs数组后$days数组的信息
Echo.
Call :%$days.Str%
Echo %$days.Str.Return%
Echo.
Echo 6.反转$days数组的元素
Call :%$days.Reserve%
Echo.
Call :%$days.Str%
Echo %$days.Str.Return%
Echo.
Echo 7.删除数组$days的数据与方法
Call :%$days.Del%
Echo.
Echo ================@Array2测试================
Echo.
Echo @Array2类继承@Array类,添加InsertStr方法
Echo.
Echo 0.创建@Array2类型的新数组$Direction
Call :@Array2 "$Direction" "East" "West" "South" "North"
Echo.
Echo 1.调用重载的Str方法,回显此数组
Echo.
Call :%$Direction.Str%
Echo %$Direction.Str.Return%
Echo.
Echo 2.$Direction.Type=%$Direction.Type%
Echo.
Echo 3.调用添加的方法InsertStr
Call :%$Direction.InsertStr% " "
Echo.
Echo 4.通过访问$Direction.InsertStr.Return回显调用结果
Echo.
Echo %$Direction.InsertStr.Return%
Echo.
Echo 5.删除对象$Direction
Call :%$Direction.Del%
Echo =================All Done==================
Echo Press any key to quit...
Pause>nul
Exit


Rem *******************************************
:@Array2
Rem 提供一个InsertStr函数增强@Array类的功能
Rem 参数:数组名 元素列表
Rem -------------------------------------------
Rem 第一次调用此类,创建类型固有信息
If not Defined $Array2.Methods (
Set $Array2.Base="Array"
Set $Array2.Fields="Type"
Set $Array2.Methods="InsertStr Str Del"
)
Rem -------------------------------------------
Rem 调用基类构造函数,创建对象
For %%a In (%$Array2.Base:"=%) Do (
Call :@%%a %*
)
Rem -------------------------------------------
Rem 初始化临时变量
Set __this=%~1
Rem -------------------------------------------
Rem 初始化对象字段
Rem 设置对象的类型信息
Set %__this%.Type="@Array2"
Rem -------------------------------------------
Rem 初始化对象方法
For %%a In (%$Array2.Methods:"=%) Do (
Set %__this%.%%a=Array2.%%a %__this%
)
Rem -------------------------------------------
Rem 销毁临时变量
Set __this=
Goto :Eof
Rem ===========================================
:Array2.InsertStr
Rem 在当前数组对象的所有元素之间插入指定字符串
Rem 参数:数组名 字符串
Rem -------------------------------------------
Rem 初始化临时变量
Set __this=%~1
Set __StrToInsert=%2
Set %__this%.InsertStr.Return=
Rem -------------------------------------------
For /L %%a In (0,1,!%__this%.UBound!) Do (
If %%a equ !%__this%.UBound! (
Set %__this%.InsertStr.Return=!%__this%.InsertStr.Return!!%__this%[%%a]:"=!
) Else (
Set %__this%.InsertStr.Return=!%__this%.InsertStr.Return!!%__this%[%%a]:"=!%__StrToInsert:"=%
)
)
Rem -------------------------------------------
Rem 销毁临时变量
Set __this=
Set __StrToInsert=
Goto :Eof
Rem ===========================================
:Array2.Str
Rem 返回当前对象的字符串表示
Rem 返回值:<数组名>.Str.Return
Rem -------------------------------------------
Rem 调用基类的Str函数
For %%a In (%$Array2.Base:"=%) Do (
Call :%%a.Str %*
)
Set __this=%~1
Rem -------------------------------------------
Set %__this%.Str.Return=!%__this%.Str.Return:~1,-1!
Rem -------------------------------------------
Set __this=
Goto :Eof
Rem ===========================================
:Array2.Del
Rem 销毁当前对象
Rem -------------------------------------------
Rem 调用基类析构函数,删除对象
For %%a In (%$Array2.Base:"=%) Do (
Call :%%a.Del %*
)
Rem 初始化临时变量
Set __this=%~1
Rem -------------------------------------------
Rem 删除字段成员

Rem 删除方法成员
For %%a In (%$Array2.Methods:"=%) Do (
Set %__this%.%%a=
)
Rem 删除返回值变量
Set %__this%.InsertStr.Return=
Rem -------------------------------------------
Set __this=
Goto :Eof
Rem *******************************************

Rem *******************************************
:@Array
Rem 提供数组的相关功能
Rem 参数:数组名 元素列表
Rem -------------------------------------------
Rem 第一次调用建立类型固有信息
If not Defined $Array.Methods (
Set $Array.Fields="Type UBound [i]"
Set $Array.Methods="Push Insert Remove Append Extend Reserve Str Del"
)
Rem -------------------------------------------
Rem 初始化临时变量
Set __this=%~1
Set __index=-1
Rem -------------------------------------------
Rem 初始化对象字段
Rem 设置对象的类型信息
Set %__this%.Type="@Array"
Rem 初始化数组元素
For %%a In (%*) Do (
Set %__this%[!__index!]=%%a
Set /a __index+=1
)
Rem 删除无用的数组元素,即位于-1索引位置的元素
Set %__this%[-1]=
Rem 设置数组的最大下标
Set /a %__this%.UBound=%__index%-1
Rem -------------------------------------------
Rem 初始化对象方法
For %%a In (%$Array.Methods:"=%) Do (
Set %__this%.%%a=Array.%%a %__this%
)
Rem -------------------------------------------
Rem 销毁临时变量
Set __this=
Set __index=
Goto :Eof
Rem ===========================================
:Array.Push
Rem 向数组开始位置压入一个元素
Rem 参数:数组名 元素
Rem -------------------------------------------
Rem 初始化临时变量
Set __this=%~1
Set /a __index=!%__this%.UBound!+1
Rem -------------------------------------------
For /L %%a In (!%__this%.UBound!,-1,0) Do (
Set %__this%[!__index!]=!%__this%[%%a]!
Set /a __index-=1
)
Set /a %__this%.UBound+=1
Set %__this%[0]=%2
Rem -------------------------------------------
Rem 销毁临时变量
Set __this=
Set __index=
Goto :Eof
Rem ===========================================
:Array.Insert
Rem 向数组的指定索引位置插入一个元素
Rem 参数:数组名 索引 元素
Rem -------------------------------------------
Rem 初始化临时变量
Set __this=%~1
Set /a __index=!%__this%.UBound!+1
Rem -------------------------------------------
For /L %%a In (!%__this%.UBound!,-1,%~2) Do (
Set %__this%[!__index!]=!%__this%[%%a]!
Set /a __index-=1
)
Set %__this%[%~2]=%3
Set /a %__this%.UBound+=1
Rem -------------------------------------------
Rem 销毁临时变量
Set __this=
Set __index=
Goto :Eof
Rem ===========================================
:Array.Remove
Rem 删除数组指定索引位置的元素
Rem 参数:数组名 索引
Rem -------------------------------------------
Rem 初始化临时变量
Set __this=%~1
Set __index=%~2
Set /a __Start=%~2+1
Rem -------------------------------------------
For /L %%a In (%__Start%,1,!%__this%.UBound!) Do (
Set %__this%[!__index!]=!%__this%[%%a]!
Set /a __index+=1
)
Set /a %__this%.UBound-=1
Rem -------------------------------------------
Rem 销毁临时变量
Set __this=
Set __index=
Set __Start=
Goto :Eof
Rem ===========================================
:Array.Append
Rem 向数组末尾追加一个元素
Rem 参数:数组名 元素
Rem -------------------------------------------
Rem 初始化临时变量
Set __this=%~1
Rem -------------------------------------------
Set /a %__this%.UBound+=1
Set %__this%[!%__this%.UBound!]=%2
Rem -------------------------------------------
Rem 销毁临时变量
Set __this=
Goto :Eof
Rem ===========================================
:Array.Extend
Rem 向数组末尾按顺序追加另一个数组的所有元素
Rem 参数:数组名 数组名
Rem -------------------------------------------
Rem 初始化临时变量
Set __this=%~1
Set __OtherObj=%~2
If not !%__OtherObj%.Type!=="@Array" (
Echo Error:要求参数%__OtherObj%是一个数组
)
Set /a __index=!%__this%.UBound!+1
Rem -------------------------------------------
For /L %%a In (0,1,!%__OtherObj%.UBound!) Do (
Set %__this%[!__index!]=!%__OtherObj%[%%a]!
Set /a __index+=1
)
Set /a %__this%.UBound+=!%__OtherObj%.UBound!+1
Rem -------------------------------------------
Rem 销毁临时变量
Set __this=
Set __OtherObj=
Set __index=
Goto :Eof
Rem ===========================================
:Array.Reserve
Rem 将数组元素位置反转
Rem -------------------------------------------
Rem 初始化临时变量
Set __this=%~1
Set /a __LEnd=!%__this%.UBound!/2
Set /a __Mod=!%__this%.UBound!%2
If %__Mod% equ 0 (
Set /a __LEnd=%__LEnd%-1
)
Set __RIndex=!%__this%.UBound!
Rem -------------------------------------------
For /L %%a In (0,1,%__LEnd%) Do (
Set __Temp=!%__this%[%%a]!
Call Set %__this%[%%a]=%%%__this%[!__RIndex!]%%
Set %__this%[!__RIndex!]=!__Temp!
Set /a __RIndex-=1
)
Rem -------------------------------------------
Rem 销毁临时变量
Set __this=
Set __LEnd=
Set __Mod=
Set __RIndex=
Set __Temp=
Goto :Eof
Rem ===========================================
:Array.Str
Rem 返回当前数组的字符串表示
Rem 返回值:<数组名>.Str.Return
Rem -------------------------------------------
Rem 初始化临时变量
Set __this=%~1
Rem 清除上次调用结果
Set %__this%.Str.Return=[
Rem -------------------------------------------
For /L %%a In (0,1,!%__this%.UBound!) Do Set %__this%.Str.Return=!%__this%.Str.Return!!%__this%[%%a]!,
Set %__this%.Str.Return=!%__this%.Str.Return:~,-1!]
Rem -------------------------------------------
Rem 销毁临时变量
Set __this=
Set __Str=
Goto :Eof
Rem ===========================================
:Array.Del
Rem 销毁当前对象
Rem -------------------------------------------
Rem 初始化临时变量
Set __this=%~1
Rem -------------------------------------------
Rem 删除对象的数据
Rem 删除对象类型信息
Set %__this%.Type=
Rem 删除数组元素
For /L %%a In (0,1,!%__this%.UBound!) Do Set %__this%[%%a]=
Set %__this%.UBound=
Rem 删除对象的方法
For %%a In (%$Array.Methods:"=%) Do Set %__this%.%%a=
Rem -------------------------------------------
Rem 销毁临时变量
Set __this=
Goto :Eof
Rem *******************************************


以上面这个@Array类为例,对批处理类的实现作一下简要说明:


1.所有类以@ClassName格式命名,如上

2.所有类在第一个此类的对象被创建之前会创建一个$ClassName.Methods和$ClassName.Fields

   变量,用于保存这个类的方法成员,它们以“.MethodName”的形式连接成一个字符串,如上面的:

   Set $Array.Methods="Push Insert Remove Append Extend Reserve Str Del"

3.当创建对象之前,首先给这个对象添加一个Type属性,它简单地保存此对象所属的类型信息,如:

  Set %__this%.Type="@Array"

  可以使用if string1==string2的方法来校验类型,如上面的:

   If not !%__OtherObj%.Type!=="@Array" (
   Echo Error:要求参数%__OtherObj%是一个数组
   )

4.而后是初始化对象数据,上面的这个是个数组类,所以我们用
  
(1)数组$ArrayName.UBound字段保存数组最大下标

(2)$ArrayName[n]保存数组元素,其中n为自然数,索引从0开始

  对象类型不同数据的储存方式也会不同,仅以上面的类为例

5.而后是给对象绑定方法,这时候$ClassName.Methods就用上了,我们从中解析出所有的Method

   并将MethodName与$ObjName绑定,如:

   $days.Push=Array.Push $days

   $days.Insert=Array.Insert $days

   ... ...
   
   $days.Del=Array.Del $days

   这样绑定之后,我们就可以按如下方式调用方法:

   Call :%$ObjName.MethodName% arg1 arg2 arg3 ...

   这与面向对象的写法很接近,如果我们想从方法中带回值,可以简单地使用$ObjName.MethodName

   作为结果的载体来返回结果,当然要注意在方法

   开始的地方将上次的调用结果清空,这个很重要

6.而后要注意的就是Del方法,它会按对象数据存储的顺序,将所有的数据清除,包括对象的类型信息,

   对象的所有数据,对象的方法绑定,还有方法的结果载体,因为方法的结果要留着访问的,所以在方法

   退出之时,结果载体应该被设置为此次调用结果,而不是被清除,所以清理工作就得由Del来做,

   当然,你不做,系统也会做
  
7.总体而言我们的代价是较大的内存花销与一定的效率损失,不过就它会在开发效率(我实在不想这么说,

   因为不觉得什么样的批处理编写能称得上是开发,规模通常太小)上得到补偿


结合上面的@Array2来说一下类的继承:


1.继承一个类只需要在派生类的构造函数中调用基类的构造函数,在派生类的析构函数中调用基类的析构


  函数就行了;


2.从派生类创建的所有对象会先由基类进行初始化,而后由派生类完成初始化,同名的成员,会被覆盖掉,


  所以,派生类一定要有一个$ClassName.Base字段,这个字段保存了基类信息,方便对基类的函数进


  行调用。另外,有了这个字段,还可以对基类某个别的方法进行调用,并使用其返回值


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值