26
2019.2

父子类的通信

作者: POPASP
在“定义控制器”的一节中,提到过控制器类的重写,比如 User控制器 ```brush:vb <% '用户模块 Class User ' 定义一个add操作方法 public sub add() '准备相关数据 end sub end Class %> ``` 会重写为 ```brush:vb <% Class [UserAction] Public that,parent,son ' 定义一个add操作方法 public sub add() '准备相关数据 end sub end Class %> ``` 这里需要注意的是,原来没有的三个属性that、parent、son,经过代码重写会自动定义。而控制器父子类的通信,主要是依据parent与son属性来完成的。that属性也很重要,使用更为频繁,它是POPASP_CONTROLLER类的实例化。 为了说明控制器父子类的通信问题,作者专门设计了下面的演示示例。 首先,定义一个控制器Test.asp,它继承Common控制器 ```brush:vb <% Class Test 'Extends Common sub index var_Export "Test.index--执行到了自己的方法
" var_Export "--调用Test父类Common的方法method
" Call parent.method end sub sub up var_Export "Test.Up
" end sub End Class %> ``` 其次,定义控制器Common.asp,它继承Top控制器 ```brush:vb <% Class Common 'Extends Top sub initialize var_export "Common.initialize--继承类的initialize总是首先被搜索并执行
" var_export "--调用父类的方法要使用parent属性
" Call parent.down end sub sub method var_export "Common.test
" var_export "--调用子类Test的方法up
" Call Son.up end sub End Class %> ``` 然后,我们定义控制器Top.asp ```brush:vb <% Class Top sub initialize var_export "Top.initialize--最顶上继承类的initialize会被最先执行到
" end sub sub down var_export "Top.test
" var_export "--调用子类的方法要使用son属性
" var_export Son.method end sub End Class %> ``` 访问 ```brush:html http://serverName/index.asp?c=test&a=index ``` 会看到输出结果 ```brush:xml Top.initialize--最顶上继承类的initialize会被最先执行到 Common.initialize--继承类的initialize总是首先被搜索并执行 --调用父类的方法要使用parent属性 Top.test --调用子类的方法要使用son属性 Common.test --调用子类Test的方法up Test.Up Test.index--执行到了自己的方法 --调用Test父类Common的方法method Common.test --调用子类Test的方法up Test.Up ``` 控制台的流程如下: ```brush:xml 准备执行 TestAction.index 发现了继承类Common,准备执行继承类 准备执行 CommonAction.initialize 发现了继承类Top,准备执行继承类 准备执行 TopAction.initialize 开始执行 TopAction.initialize 执行结束 TopAction.initialize 开始执行 CommonAction.initialize 执行结束 CommonAction.initialize 开始执行 TestAction.index 执行结束 TestAction.index ``` 这样的一个复杂案例告诉我们,控制器Test的父类Common的实例化可以用parent访问,同样Common的父类Top的实例化也可以用parent访问,这两个parent所指代对象是不一样的,前者指的是Common,后者指的是Top。 通过parent、son两个属性可以完成一些复杂的操作,在前面的“控制器的继承”音节中,我们遗留了一个问题,那就是如何摆脱控制器的爬楼梯现象,而返回子类执行后置操作,有了本节的知识,那么解决这个问题就很简单了。 控制器Common的代码 ```brush:vb <% Class Common sub initialize var_export "Common.initialize
" end sub sub add var_export "Common.add
" end sub sub after__add var_export "Common.after__add
" end sub End Class %> ``` 控制器Nav的代码 ```brush:vb <% Class Nav 'Extends Common sub before__add var_export "Nav.before__add
" end sub sub add '在这里定义方法add,并且让它执行父类的add方法 Call parent.add end sub sub after__add var_export "Nav.after__add
" end sub End Class %> ``` 访问 ```brush:html http://serverName/index.asp?c=nav&a=add ``` 得到的结果如下: ```brush:xml Common.initialize Nav.before__add Common.add Nav.after__add ``` 从结果中可以看出父类的方法也执行到了,自身的后置操作也执行到了。 注意观察控制台的“流程”,也能看见执行了自身的后置操作 ```brush:xml 准备执行 NavAction.add 发现了继承类Common,准备执行继承类 准备执行 CommonAction.initialize 开始执行 CommonAction.initialize 执行结束 CommonAction.initialize 发现了前置操作 NavAction.before__add 开始执行 NavAction.before__add 执行结束 NavAction.before__add 开始执行 NavAction.add 执行结束 NavAction.add 发现了后置操作 NavAction.after__add 开始执行 NavAction.after__add 执行结束 NavAction.after__add ``` 我们以iaspcms后台的common.asp举例 ```brush:vb <% Class Common Sub switch_status on error resume next dim id id = check_id dim statusField statusField = Son.statusField if err.number <> 0 then statusField = son.tableName & "Status" end if if B_(son.tableName).where( id ).setNot(statusField) then that.redirect("") end if End Sub End Class %> ``` 在上面的类common中son.tableName就是指子类的表名,我们在common父类中写switch_status方法,就省去了在很多控制器中写相同代码的麻烦。