我公司在開發醫院信息管理系統的過程中,由于系統龐大,遇到這樣一個棘手的問題:
我們制作了若干個用戶自定義的數據窗口對象, 每個對象中封裝了一個獨立的功能, 如: 數據窗口排序功能,用戶自定義列校驗功能,下拉數據窗口快速錄入功能,大文本錄入功能,回車到下一列功能等等, 共12個功能對象, 由不同的人制作.
我們需要任意選取其中的某幾個功能對象做為祖先繼承, 由于PB不允許一個對象同時繼承不同的祖先,且祖先一旦確定, 就不允許改變. 如果將這12個用戶自定義數據窗口對象的功能全部封裝到一個用戶自定義數據窗口對象中, 雖然能解決繼承問題, 但是該對象會很龐大,對象內部邏輯變得更復雜, 更難以維護,一些在調用時用不上的功能, 勢必會在運行時消耗更多的系統資源. 既然繼承的路走不通, 筆者就想出了一個對象變量引用的方法.
二、解決問題的思路
首先筆者引入了二個概念(指用戶定義的數據窗口對象):
1. 基本功能對象: 具有單一功能的,獨立的,用戶自定義的對象.
2. 中間層對象: 把自己捕獲到的事件以某種方式傳遞給基本功能對象實例變量, 以完成對基本功能對象相應的事件腳本的調用. 被繼承, 但不繼承任何其它對象.
另做一個用戶自定義數據窗口對象,它不繼承任何對象, 稱之為中間層對象, 在中間層對象中為每個需要用到的基本功能對象聲明一個實例對象變量, 在中間層對象的事件中去調用實例對象相應的事件. 使用時繼承中間層對象, 以完成對基本對象的選擇與調用.
實現舉例:
1. 基本功能對象制作:
新建二個數據窗口用戶對象, 分別命名為: Uo_DwA, Uo_DwB . 在Uo_DwA 的Clicked 事件中寫一行腳本:
MessageBox ( ' Uo_DwA ' , ' Uo_DwA 的單擊事件')
在Uo_DwB 的Clicked 事件中寫一行腳本:
MessageBox ( ' Uo_DwB ' , ' Uo_DwB 的單擊事件')
2. 中間層對象制作:
2.1新建一個數據窗口用戶對象, 命名為 Uo_DwInterlayer .
2.2為中間層對象聲明二個實例變量:
GraphicObject Igo_BaseDwObject[] //每一個元素是一個基本對象的實例引用 Integer Ii_BaseDwObjectNumber //保存元素的個數.
2.3. 加一個用來注冊的對象函數, 用來注冊基本功能對象.
Uf_Register (GraphicObject a_obj[] , DataWindow adw_object)
函數內容:
Long Ll_Circulater
Ii_BaseDwObjectNumber = UpperBound (A_Obj[])
FOR Ll_Circulater = 1 TO ii_basedwobjectnumber
Igo_BaseDwObject[Ll_Circulater] =
A_Obj[Ll_Circulater]
// 下行腳本用來注冊基本功能對象中的實例變量
Idw_THIS (說明見下文)
//Igo_BaseDwObject[Ll_Circulater].Function
Dynamic Uf_RegisterDwo ( Adw_Object)
END FOR
Return
2.4為中間層對象中加入每個基本功能對象擁有用戶自定義事件, 在中間層對象的每個事件中加入如下腳本(事件Clicked):
Long Ll_Circulater
//調用被注冊過的每個基本功能對象的相同的事件腳本
FOR Ll_Circulater = 1 TO Ii_BaseDwObjectNumber
//如果當前事件為EditChanged , 則把下行腳本中的Clicked(xpos , ypos , row , dwo) 部分替換為 EditChanged(row,dwo,data)
Igo_BaseDwObject [Ll_Circulater].Event
Dynamic Trigger Clicked (xpos , ypos , row , dwo)
END FOR
Return
3. 新建一個窗口, 命名為W_TestInterlayer . 在窗口中放置中間層對象: Uo_DwInterlayer . 默認控件名: Dw_1. 然后在控件Dw_1的Constructor 事件中對需要引用的基本功能對象進行注冊, 即可實現引用基本功能對象的目的. 基本功能對象可以是任意個.
在Dw_1 的Constructor 事件中加入如下腳本:
//注冊基礎數據窗口對象
GraphicObject Lgo_BaseDwObject []
//聲明一個可變長度的一維對象數組
//建立對象數組元素的實例, 以便對Uo_DwA進行引用
Lgo_BaseDwObject[1] = Create Uo_DwA
//建立對象數組元素的實例, 以便對Uo_DwB進行引用
Lgo_BaseDwObject[2] = Create Uo_DwB //
//用中間層函數注冊對象數組和本數據窗口對象.
Uf_Register ( Lgo_BaseDwObject[] ,THIS)
Return
4. 運行窗口W_TestInterlayer , 單擊 DW_1 , 會依次彈出2個消息框.
在實際應用中, 由于基本功能對象是被引用的而非繼承, 所以基本功能對象腳本中的代詞THIS為空, 為此:
需要在基本功能對象中聲明一個實例變量: DataWindow Idw_THIS .
加一個注冊函數用來為實例變量Idw_THIS 賦值. 函數名稱 Uf_RegisterDwo (DataWindow , Adw_THIS) .
函數內容:
Idw_THIS = Adw_THIS
Return
對象中所有對數據窗口操作的函數前都必須加上 “Idw_THIS.”, 進行完全路徑的引用.
因為這些基本功能對象被繼承過,為了向前兼容, 所以要在它們的Constructor 事件中寫入如下腳本:
IF Not IsValid (Idw_This) THEN
Idw_This = THIS
END IF
Retrun
以便對實例變量Idw_THIS 自動賦值.
文章來源于領測軟件測試網 http://www.kjueaiud.com/