ABAP OO的八大理由(六)
原因二,实例化
对象的实例化是面向对象编程的一个重要特点。在ABAP OO中,通过实例化你可以实现一个类的多个变体,这样程序员便可以调用任何一个对象并让他完成相应的功能(比如一个银行帐号的收款存款和窗户的打开关闭等)。
在面向过程的编程中,当程序内容被编译到内存中便隐含着一个实例化的过程,但是这个实例并不能为程序员显式的调用,因为这需要数据和功能的分离,而面向过程的的程序员并不是直接对对象进行操作,而是要告诉一个功能模块需要修改那些数据(比如需要告诉功能模块那个银行帐号要付款或者那个窗户要打开)。下面我们将详细描述这两种不同的实例化之间的区别。
面向过程的实例化
大多数程序员可能没有意识到其实在面向过程的程序里也有类似于对象实例化的现象。程序本身在被调入内存的时候其实就是一个隐含的实例化过程,因为程序本身被调用或者程序中的某个过程被其他程序调用了。
模块池隐含实例化的例子
DATA: id1(8) TYPE n,
Id2(8) TYPE n,
Amnt TYPE p DECIMALS 2,
Exc_ref TYPE REF TO cx_negative_amount,
Text TYPE string.
TRY.
Id1 = …..
Id2 = …..
Amnt = …..
CALL FUNCTION ‘TRANSFER’
Id_from = id1
Id_to = id2
Amount = amnt.
CATCH cx_negative_amount INTO exc_ref.
Text = exc_ref->get_text().
MESSAGE text TYPE i.
ENDTRY.
上面的例子演示了调用银行账户模块池的转账功能模块的例子,两个银行账户是通过账户ID来区分的。
如果银行账户模块池中的功能模块是第一次被调用,那么整个模块池就会被调到调用程序的内部session中,模块池的LOAD-OF-PROGRAM事件就会被触发。对应的事件部分充当着模块池实例化的结构事件。如果在同一个内部session中,在同一个程序或另一个程序中银行帐号模块池已经被调用,那么下一调用,模块池已经被装载到这个内部session中。由于程序或者过程只有一次装载到内存的过程,所以功能模块便可以使用其所在模块池中的全局数据。
这种实例化对于数据封装带来了如下缺陷:
l 你无法控制实例化的时刻(在一个较大的程序中功能模块在任何时候,任何地点都有可能被调用),这样当一个程序在调用功能模块的时候它将无法知道是否另一个程序或过程改变了模块池的全局数据。
l 你无法在内存中删除模块池的实例,因为模块池的实例的生命周期取决于调用主程序的生命周期。如果你想在模块池的全局数据中使用数据量较大的变量,那么你在使用后需要手工将其清除。另外模块池一般是许多功能模块的容器,这样就会给内存带来很大的压力,即便是你只是在较短的时间调用很简单的功能模块。
l 每个程序在内存中只能创建一个实例。正如我们在原因1种所看到的,这就限制了我们充分发挥模块池的数据封装性。
还要注意的如果在模块池中,全局变量不能被整取操作,那么将是功能模块对全局变量的使用变得更加危险。全局变量的状态取决于功能模块的调用顺序,尤其是在一个大程序里,功能模块在不同的地方都有可能调用,这样就导致了模块池全局变量状态的不稳定。