




已阅读5页,还剩20页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
ABAP OO的八大理由 几年前SAP BASIS 4.6为ABAP扩展了OO功能,这是很多传统的ABAP程序员陷入困境。首先对于ABAP程序员来说它们终于可以通过OO这种开发方法得潜在价值来提高开发效率和所开发程序的可维护性了。然而一直以来习惯于面向过程编程的ABAPER迅速的转向OO模式也不是那么容易,很多人还是坚持使用传统的面向过程的开发模式,他们觉得不用OO也可以得到他们想要的。这篇文章的主要目的便是让你明白OO能给你带来什么以及如何转型为OO模式。很多关于ABAP OO方面的文章要么过于抽象,要么举的例子过于简单对于实际应用无关痛痒。本篇文章力图通过简单而又切合实际的例子通过面向过程和面向对象两种模式的比较来说明OO的优点。1. 首先ABAP OO具有更高层次的数据封装性,从而增强了程序的可维护性和稳定性。在面向过程的模式里,一个程序的全局变量区包含着许多不相干的变量,这些变量在一个区域里交织在一起,这样的话这个程序的某个功能对程序状态的改变并不为程序中另外一个功能所知。为保持整个程序的稳定性需要大量的约束和维护成本。而对于OO模式,状态是保存在对象上的。对象可以把内部和外部数据和方法分隔开,以保证功能(OO中的方法)只能改变与它相关的数据,对象的属性是不会被改变的,从而保证了其在应用程序中的稳定性。2. ABAP OO可以实现一个类的多个实例。(对象是由数据以及操作数据的方法组成的。),每一个对象都有自己在类中定义的属性值,并且可以通过本身的方法来改变本身的状态。这就意味着开发者无需为每个对象建立数据和方法之间的联系也无需手工管理每个对象的生命周期。在面向过程的方法中没有多实例的概念,数据和功能是相互分离的。你使用的是无状态的功能,并且每次都需要通过传递参数来初始化它,并且手工将其占有的内存清除。3. ABAP OBJECT通过继承进一步增强了程序代码的可重用性,这正是面向对象方法的一个重要方面。通过这个特点你可以重复利用所继承类的部分或者所有方法,只需编写类本身所特有的方法,这样会减少为每个类编写的方法,从而增强了程序的可维护性。而对于面向过程的编程来说,你将会受制于all-or-nothing的状况,你要么调用所有的部分要么就建立新的。4. ABAP OO是你可以通过接口(interface)来调用对象的业务逻辑,而不是直接去使用对象,这样就避免了你需要详细了解每一个对象的特定功能。这样也避免了你在需要修改某项功能的时候无需修改接口(interface)的内容,这也为标准程序的修改提供了新的途径,即BADI。面向过程的编程并没有这种提供对立的接口去联系某个对象的概念接口只是通过form或function module的参数实现的。5. ABAP OO非常容易与事件驱动的模式结合在一块。不同的应用之间是通过发布与预定松散的耦合在一起的,调用者和被调用者之间并不是被动的绑定在一起的。这种方式与面向过程的方法相比更进一步的增强了灵活性,他们的绑定是紧密地,程序的执行流程也是预定义好的。当然,这些好处都需要你今后在开发中是用OO的方法来开发才能得到。然而重新建模你应用程序的开发模式是令人沮丧和头疼的,我们保证这种情况不会出现,读完这篇文章我们相信你会得到同样的结论。当然,没有说我们需要重新建模已有的应用,我们只是希望你在今后的开发过程中最后考虑一下OO的模式。如果你坚持认为面向过程的模式对你来说已经足够了,也请接着往下读。通过使用对象的方法来代替form和function module你仍然可以增强你的ABAP程序。1. ABAP OO更加明确所以更易于使用。例如在使用ABAP OO你的程序的执行流程不再是由运行时隐含的控制。这样你就可以自己去设计程序所执行的流程了而不必像面向过程那样去了解和服从外部控制机制(即报表和dialog screen的事件)。2. ABAP OO具有更加清晰的语法和语义规则,比如一些容易出错的过时的语句在ABAP OO类中已经明确不能再使用。而在面向过程的程序中这些语法仍然被支持,顶多就是在关键的时候给你报个警告信息。3. ABAP的一些新技术只能通过ABAP OO来实现。例如所有新的GUI的概念比如SAP Control Framework和BSP只有通过ABAP OO的方式才能够实现。而对于面向过程的ABAP你就只能使用传统的screen和list processing了。所以即便你在未来的开发中还不准备完全的转型为OO,你可以使用的OO技术来减少错误的隐患以及增强代码的可维护性。下面的部分将会阐述如何达到这一目的。那么面向过程的ABAP和ABAP OO究竟是孰优孰劣?下面的部分将逐一进行论述。首先先了解以下ABAP OO的年代史。1. SAP Basis Release 4.5发布了ABAP OO的一个版本,引入了类接口的概念,并可以通过类来创建对象(实例化类)。2. SAP Basis Release 4.6发布了ABAP OO的完全版本,引入了OO方式的重要概念继承(inheritance),可以通过多个接口来建立一个复合的接口。3. SAP WEB APPLICATION SERVER 6.10/6.20 SAP basis的下一代版本,在类之间引入了friendship的概念。并引入了对象服务(object service)可以把对象存储在数据库中。4. SAP WEB APPLICATION SERVER 6.40引入了共享对象(Shared Objects)的概念,即允许在应用服务器的共享内存中存储对象。这样在这个服务器中的任何一个程序都可以访问它。几个关键点n ABAP OO是ABAP编程语言的扩展n ABAP OO 是向下兼容的n SAP发布ABAP OO是为了进一步增强代码的可重用性n 随着ABAP OO的发布,ABAP运行时支持面向过程和面向对象两种模式对于面向过程的模式,程序的运行通常是从screen的dialog module或selection screen的start-of-selection事件开始的。你在这些处理模块中操作全局变量来实现需求的功能。你可以通过内部的form和外部的function module来实现程序的模块化。这些过程除了可以操作全局变量外还可以具备内部的本地变量来协助实现内部的一些特定功能。对于OO编程,唯一的结构单位就是类,这里类的实例对象取代了全局变量。这些对象封装了应用的状态和行为。应用的状态是用属性来代表的它取代了面向过程中的全局变量。应用的行为是通过方法来实现的,他们用来改变应用的属性或者调用其它对象的方法。n ABAP OO支持OO和面向过程的两种模式,这样在传统的ABAP程序(比如报表,模块池,功能池等)中你也可以使用ABAP对象类。在这些程序里你也就可以使用基于面向对象的新技术了,比如一些用户界面,避免了要想使用这些新技术必须重新编写程序。n 目前大部分程序都是面向过程和ABAP OO 的混合体如下图所示: 左边是纯粹的ABAP OO模式,所有的代码都封装在类中。你的应用中并不直接触presentation layer(SAP Gui , Business Server Pages etc.),persistent data(database table,system file)。他们是通过类库中的相应服务类来提供的。比如SAP Control Framework ,Desktop Office Integration, and Business Pages提供了与表现层的接口。对于SAP Web Application 6.10以上提供了与数据库层接口的服务对象。虽然纯粹的OO模式技术上是可行的,但是现实中还存在着大量的两种模式的混合体如右面的图所示。ABAP 对象和面向过程的技术同时应用,调用常用的功能模块,调用屏幕或者直接访问数据库等在对象中都存在。混合的模式及利用了新技术又保护了已投入的成本。两种模式的选择正如本文所述,OO的模式是最佳的选择,除非在绝对必要的情况下才使用面向过程的模式。比如传统的screen programming在OO中是不支持的,附录中会进一步阐释如何实现screen与OO的结合。OO编程优于过程编程的五个原因下面的部分里我们将着重论述OO编程的主要优点,尽管这里所提到的优点与其他的OO语言(JAVA C+)没有什么太大的区别,我们这里着重在ABAP OO与传统的ABAP程序相比而体现出来的优点。我们将通过实现一个银行账户管理的简单例子来比较两种模式的差别。原因一:数据封装将数据和程序封装在一个组件中将使程序变得容易修改。不要把一个应用的所有的数据和功能放在同各超长的程序里,你只需要把你的应用通过组件的稳定的接口把需要的部分包进来即可。如果一个封装的组件有一个好的接口,而这些接口的设计比较完善的话,那么这些接口的内部结构就会被很好的隐蔽起来,对这个部件的内部的修改便不会影响到应用的其他部件。让我们来看看面向过程和面向对象的方式是如何实现封装的。面向过程模式的封装在面向过程模式中有两种变量:全局变量:他在程序的全部分声明,可以在程序的任何部分应用。局部变量:他在某个过程(form of function module)中声明也只能在其中应用。全局变量的生命周期取决于整个程序的生命周期,局部变量的生命周期取决于该过程的生命周期。由于生命周期的限制,局部变量不适合于封装,它是过程中为了达到某个目的而使用的辅助变量。如果没有使用TABLES和COMMON PARTS语句那么程序中所声明的全局变量只能被该程序内部的各个模块调用。那么这就决定了在面向过程的模式中数据的封装只对程序本身有效。下面是一个简单的如何通过功能池实现对一个银行帐号的封装。Function-pool AccountDATA: current_account TYPE accounts-amount.Function deposit. * IMPORTING REFERENCE(amount) TYPE account-amountCurrent_amount = current_amount + amount.EndFunction.Function withdraw.* IMPORTING REFERENCE(amount) TYPE account-amount* RAISING * CK_NEGATIVE_AMOUNT IF current_amount amount. Current_amount = current_amount amount. ELSE. RAISE EXCEPTION TYPE CK_NEGATIVE_AMOUNT. ENDIF.ENDFUNCTION.这个模块池封装了银行账户的余额,并且通过功能模块deposit和withdraw来处理银行账户的余额。虽然单单是一个银行帐号的话这个模块池工作的非常好,但如果是多个银行帐号并要实现银行帐号之间交互的功能,问题就出现了。为了实现现实世界中多个银行帐号的管理,你不得不为每一个银行帐号建一个唯一名字的模块池和功能模块,这显然是不可取的。下面是个把所有银行帐号封装在一个模块池中的例子:FUNCTION-POOL accounts. DATA: account_table TYPE SORTED TABLE OF accounts WITH UNIQUE KEY id.ENDFUNCTION.LOAD-OF-PROGRAM. SELECT * INTO TABLE account_table FROM accounts.FUNCTION deposit.* IMPORTING * REFERENCE(id) TYPE accounts-id* REFERENCE(amount) TYPE accounts-amountDATA: account_wa TYPE accounts.READ TABLE account_tabe INTO account_waWITH TABLE KEY id = id.Account_wa-amount = account_wa-amount + amount.MODIFY account_table FROM account_wa. ENDFUNCTION.FUNCTION withdraw.* IMPORTING * REFERENCE(id) TYPE accounts-id* REFERENCE(amount) TYPE accounts-amount* RAISE* CX_NEGATIVE_AMOUNTDATA: account_wa TYPE accounts.READ TABLE account_tableINTO account_waWITH TABLE KEY id = id.IF account-amount amount. Account-amount = account-amount amount. MODIFY account_table FROM account_wa.ELSE. RAISE EXCEPTION TYPE CX_NEGATIVE_AMOUNT.ENDIF.ENDFUNCTION.FUNCTION transfer.* IMPORTING * REFERENCE(id_from) TYPE accounts-id* REFERENCE(id_to) TYPE accounts-id* REFERENCE(amount) TYPE accounts-amount* RAISE* CX_NEGATIVE_AMOUNT CALL FUNCTION withdraw EXPORTING id = id Amount = amount. CALL FUNCTION deposit EXPORTING id = id Amount = amount. ENDFUNCTION.这样多个银行帐号就被封装在内表account_tab中,每个银行帐号是通过关键字ID来区分的。内表account_tab在模块池被调用时被填充以便模块池中的所有功能模块都可以使用它。功能模块deposit和withdraw通过id来处理一个银行帐号,而新的功能模块transer来实现两个银行帐号之间的转账。这样我们通过一定的技巧实现了多个银行帐号的管理但是为了区别每个银行帐号却增加了每个功能模块接口参数的复杂性。面向对象模式的数据封装OO模式的编程也有两种数据类型,类实例的属性和类方法中的本地变量。实例属性的生命周期依赖于对象的生命周期,本地变量的生命周期依赖于类方法的生命周期。所以面向对象的本地变量与面向过程的本地变量的生命周期是一样的。它是类方法中的辅助变量与数据封装无关。ABAP对象的数据封装在类这个级别。可以定义类属性的可见性,它的级别分别是在类内可见,在子类中可见,或者在外部类中可见。下面的例子演示了如何在类中封装银行账号:CLASS account DEFINITION. PUBLIC SECTION.METHODS: constructor IMPORTING id TYPE account-id, Deposit IMPORTING amount TYPE accounts-amount, Withdraw IMPORTING amount TYPE accounts-amountRAISING cx_negative_amount, Transfer IMPORTING amount TYPE accounts-amount Target REF TO account RAISING cx_negative_amount.PRIVATE SECTION. DATA amount TYPE accounts-amount.ENDCLASS.CLASS account IMPLEMENTATION. METHOD constructor. SELECT SINGLE amount INTO (amount) FROM accounts WHERE id = id. ENDMETHOD. METHOD deposit. Me-amount = me-amount + amount. ENDMETHOD. METHOD withdraw.IF me-amount amount. Me-amount = me-amount amount.ELSE. RAISE EXCEPTION TYPE cx_negative_amount.ENDIF. ENDMETHOD. METHOD transfer. Me-withdraw( amount ). Target-deposit( amount ). ENDMETHOD.ENDCLASS.在account类的定义部分可以定义属性和方法的可见性(private public)。类的定义把功能和数据结合到了一块。理论上,前面例子的功能池也做到了这点,只不过在不同的数据模块间进行交互的时候就暴露了其局限性,所以功能池只能说是多个功能模块的容器还不能真正的共享数据。在ABAP OO的类中PUBLIC部分定义了其与外部交互的接口。在这个例子中描述类状态的属性是私有的,而对外的公共接口是操作这些属性的方法。这个例子中的类既实现了前面面向过程的第一个例子的简单功能也实现了第二个例子较为复杂的功能。这个类的deposit,withdraw方法与第一个例子的两个功能模块的作用相同,由于你可以创建一个类的多个对象,所以这个类只需封装一个银行帐号的数据即可,constructor方法用来为不同的银行账号初始化数据。由于每个对象都有它自己的数据,所以你不需为类添加额外的参数。最后,不止于此,由于一个对象可以调用另外一个对象的方法,那么不同银行账号之间的交互便有了更加简洁的方案,这例子中transfer功能的实现要比前面第二个例子的实现简单的多。原因二,实例化对象的实例化是面向对象编程的一个重要特点。在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种所看到的,这就限制了我们充分发挥模块池的数据封装性。还要注意的如果在模块池中,全局变量不能被整取操作,那么将是功能模块对全局变量的使用变得更加危险。全局变量的状态取决于功能模块的调用顺序,尤其是在一个大程序里,功能模块在不同的地方都有可能调用,这样就导致了模块池全局变量状态的不稳定。面向对象的实例化行如其名,在面向对象的模式中,对象是唯一存在的东西。对象是类的实例,是通过CREATE OBJECT语句来实现的。ABAP对象不可能被隐含的实例化,你通过指针变量来操作对象。当然你通过指针所操作的对象不一定是自己创建的,这种现象主要是通过指针操作的对象很有可能是从其他地方传过来的,比如说工厂方法(factory method)或者接口参数。你可以在一个类中创建多个对象每个对象通过属性都有自己的标识符和内容。对象的生命周期是由使用者来控制的(其他对象,程序或过程等),只要有指针变量指向他,他就在内存中存在。如果没有指针变量指向对象,这个对象就会被自动的被ABAP内存收集器从内存中删除。和程序的实例一样,ABAP对象也存储在主程序的内部SESSION中。在640之后你就可以在应用服务器的SHARED MEMORY中创建shared object了,这样在这应用服务器上运行的任何程序都可以调用它。下面的例子演示了从银行账号类中产生的两个银行账号对象。DATA: account1 TYPE REF TO account, Account2 TYPE REF TO account, Amnt TYPE p DECIMALS 2, Exc_ref TYPE REF TO cx_negative_amount, Text TYPE string.CREATE OBJECT : account1 EXPORTING id = ., Account2 EXPORTING id = .TRY. Amnt = . Account1transfer ( EXPORTING amount = amnt Target = account2). CATCH cx_negative_amount INTO exc_ref. Text = exc_ref-get_text(). MESSAGE text TYPE i.ENDTRY.指针变量account1,account2是类account的对象的显示的操作符。在CREATE OBJECT语句中每个账号标识被传入到了对象的结构体。对象一旦被创建,账号标识就不用再被声明了。你可以调用一个对象的transfer方法,通过账号指针变量来指明要转入的账号。与面向过程的上面的例子相比,显然面向对象的例子更加直接。在面向过程的例子里你不得不为每个功能模块指明要操作的数据,而在面向对象的例子里你只需调用对象的方法那么他就会自动地使用它自己的数据。值得注意的是例外信息我们都是使用基于类的方法,这在610之后是被推荐的。在面向过程的程序中使用指针变量exc_ref显得有些另类,因为在非OO模式的程序中使用了OO模式的东西,这也是ABAP OO的一个自然特性。原因三:代码重用性代码重用性是软件维护和开发的一个重要衡量指标。我们应当把一些通用的代码放在一个中心库里,而无须一遍一遍的重复编写功能相似的代码。下面就在代码重用方面检查一下ABAP OO和ABAP OP孰优孰劣。面向过程的代码重用性在面向过程的模式中没有什么专门的机制来支持代码的重用性。你可以定义通用的过程,但是如果你想在特殊情况下使用通用代码,你不得不建立很庞大的模块池,每个功能模块又不得不有复杂的参数,而每个功能模块中你又不得不使用复杂的分支语句,例如SWITCH CASE.。比如为了给银行账号加入两个特殊的账号,检查账号和存款账号,我们不得不修改我们的程序以支持这种变化。下面的例子演示了对功能模块withdraw的修改。FUNCTION withdraw. CASE kind. WHEN C. PERFORM withdraw_from_checking_account USING id amount. WHEN S.PERORM withdraw_from_savings_account USING id amount. WHEN OTHERS. RAISE EXCEPTION TYPE cx_unknown_account_type. ENDCASE. ENDFUNCTION.FORM withdraw_from_checking_account. USING i_id TYPE accounts-id Amount TYPE accounts-amount. DATA: account_wa TYPE accounts. READ TABLE account_tab WITH TABLE KEY id = i_id INTO account_wa. Account_wa-amount = account_wa-amount amount. MODIFY TABLE account_tab FROM account_wa. IF account_wa-amount i_amount.Account_wa-amount = account_wa-amount amount.MODIFY account_tab FROM account_wa. ELSE. RAISE cx_negative_amount. ENDIF.ENDFORM.这样你就不得不增加新的参数帐户类型了在这个例子中还得增加新的例外信息,即如果帐户类型不在合理范围之内的情况。最终为了实现对不同的帐户类型采取不同的处理逻辑,那么你就不得不写两个form来分别处理两种不同的情况。ABAP OO的代码可重用性在ABAP OO中通过继承来实现代码的可重用性,可以通过通用的父类来派生特殊的子类。这样好处是简单的类既可代替代码庞杂的模块池,简单的方法参数既可代替功能模块复杂的参数,最重要的是通过继承实现了类的多态。这样就实现了子类的对象仍然可以使用父类的方法。这大大增强了软件开发的建模能力。下面的例子是一个修改版的帐户,他已经作为两个子类checking account和saving account的父类。CLASS account DEFINITION. PUBLIC SETION. PROTECTED SETION. DATA amount TYPE accounts-amount.ENDCLASS.CLASS account IMPLEMENTATION. METHOD withdraw. ME-amount = ME-amount amount. ENDMETHOD.ENDCLASS.正如你所见属性amount已经由private改为protected以便它的两个子类也可以放问它。方法withdraw已经被通用化,它不再抛出异常。这些改变外界不会察觉到,这也是实现多态的前提条件。父类account的子类checking accountCLASS checking_account DEFINITION INHERIATING FROM account. PUBLIC SECTION. METHODS withdraw REDEFINITION.ENDCLASS.CLASS checking_account IMPLEMENTATION. METHOD withdraw.Super-withdraw ( amount ).IF me-amount amount amount. Me-amount = me-amount amount.ELSE. RAISE EXCEPTION TYPE cx_negative_amount.ENDIF. ENDMETHOD.ENDCLASS.通过INHERIATING FROM使得父类和子类有着相同的属性和参数。通过方法withdraw REDEFINITION来重新编写子类的同名方法。通过super-可以调用父类的方法,在两子类中这两个withdraw方法根据不同的帐户类型作了改动,例如在这两个子类中分别对当帐户余额为负数是抛出异常或者贷向处理。下面的例子演示了一个父类,两个子类的使用:DATA: account1 TYPE REF TO account, Account2 TYPE REF TO account, Amnt TYPE p DECIMALS 2, Exec_ref TYPE REF TO cx_negative_amount, Text TYPE string.CREATE OBJCET account1 TYPE checking_account EXPORTING id = .CREATE OBJCET account2 TYPE savings_account EXPORTING id = TRY. Amnt = Account1-transfer( EXPORTING amount = amnt Target = account2 ). CATCH cx_negative_amount INTO exec_ref. Text = exec_ref-get_text(). MESSAGE text TYPE i.ENDTRY.与前面的面向对象的例子相比,唯一的不同便是在创建对象是,类别分别改为checking_account和savings_account。不过account1和account2在变量声明部分仍然使用的是类account。对于上面的例子除了对象指针变量,对于使用它的程序,它与前面的例子,程序感觉不到他有什么区别,然而不同类型的对象会自动调用属于自己的方法。这样的好处是显而易见的,在面向过程的功能模块中为了实现不同类型帐户之间的转账你为此不得不付出成级数倍的增长,而在面向对象的模式中我们无需改变transfer方法。原因4:INTERFACEINTERFACE通俗的讲就是通过一个程序来调用另外一个程序的数据和功能。在模块化和相互访问的世界中,INTERFACE提供了两个部件之间联系的桥梁。在ABAP OO中提供了类与调用者之间独立的INTERFACE,这样就把类和使用者之间分离开来。而在ABAP OP(oriented procedure)中没有独立的INTERFACE,而是提供了程序之间隐式的INTERFACE和程序和过程之间显式的INTERFACE。我们来进一步研究一下这两种模式的INTERFACE。面向过程的INTERFACE面向过程的INTERFACE有一定的局限性。l 用TABLES或COMMON PART声明的全局变量便是程序之间隐式的INTERFACE,在经典的ABAP语言中一旦用TABLES定义了全局变量,就隐含的定义了屏幕与程序之间的接口。逻辑数据库也使用了这种隐式的接口方式。l 一个程序的过程可以被另外一个程序调用,是程序之间的功能INTERFACE。程序中的功能模块和form都是公开的。从外边调用的其他程序的form或功能模块的程序可以访问他们所在的主程序的变量。当用SUBMIT调用程序的时候,除了可以用selection screen上的parameters或select options作为显式的INTERFACE外,程序之间在没有其他显式的INTERFACE了。如果开发人员修改了一个程序的隐式INTERFACE,可能会导致调用这个程序的其他程序失效而开发者确感觉不到这一点。让外部程序无限制的去访问主程序中的数据是有风险的。OO的INTERFACE在OO模式中可以定义INTERFACE的三个访问级别:PUBLIC,PRIVATE,PROTECTED。PUBIC表示功能或数据是对外开放的。PRIVATE指明INTERFACE只能在类内部使用而PROTECTED则说明只有其本身或者其子类可以访问。而对于友好类则可以访问PROTECTED和PRIVATE部分。对于子类,其继承了父类的INTERFACE,并可以对其进行扩展。为了提高稳定性和可重用性,可以把类的PUBLIC部分单独分离出来做为类对外INTERFACE的独立描述。这种INTERFACE没有任何具体的代码,它只有类的全部或部分全局属性。独立的INTERFACE可以被多个类使用,它代表了类的某个具体方面,比如统一持久属性等。因为他们与具体的功能无关,所以一个对象的不同特性可以建立不同的INTERFACE,他们之间的关系如下图所示:INTERFACE通过语句INTERFACE.ENDINTERFACE来定义。它可以有与类一样的部件。任何类都可以有一个或多个INTERFACE。通过在类的public部分进行声明,这样在interface中定义的public部分就成为类public interface的一部分。包含独立interface的类必须为类提供服务,这样用户可以通过interface来访问类,而无需知道其中的访问细节。那么,实现这种机制的原理是什么呢?基本原理是你可以声明指针变量,而这个指针变量可以指向实施这个interface的任何类的对象。调用者只是与interface指针变量工作,而其无需知道其实际指向的是哪个类的对象。而调用者只需知道这个interface的相关属性就可以了。因为实现interface的类,就会实现在interface中定义的部分,所以只要通过interface调用者就可以实现自己的目的了。每个interface按照自己的目的定义自己的interface方法。比如不同类型的银行帐号,利息计算的方法不同。在interface中方法名和其参数是相同的。所以interface和继承是OO中实现多态的两种方式。通过interface指针变量来访问对象与通过父类的指针变量来访问子类的对象的道理一样。下面的例子演示了两个毫无关系的类,account和customer:CLASS account DEFINITION. PUBLIC SECTION.INTERFACES if_serializable_object.ENDCLASS.CLASS customer DEFINITION. INTERFACES if_serializable_object.ENDCLASS.DATA:account TYPE REF TO account, Customer TYPE REF TO customer, Serializable_objects TYPE TABLE OF REF TO if_seriazable_object, Serializable_object TYPE REF TO if_serializable_object, Xmlstr TYPE string.CREATE OBJECT accout EXPORTING id = , Customer.APPEND: account TO serializable_objects, Customer TO serializable_objects.LOOP AT serializable_objects INTO serializable_object. CALL TRASFORMATION id SOURCE obj = serializable_object RESULT xml = xmlstr.ENDLOOP.Account是我们所熟悉的类,customer可能是整个业务应用的一部分或其他的什么,这都无所谓。但是这些类都有统一的interface,这是在6.10之后所支持的。本例中的interface可以使你把对象的属性序列化到xml文档中。具有INTERFACE if_serializable_object的类都具备了序列化的属性并对外提供了这种属性。上面的例子演示了如何使用类account和customer的接口,在这个例子中,内表serializable_objects作为if_serializable_object指针变量的集会。假如说在程序中的某个部分,内表被遍历,那么通过语句CALL TRANSFORMATION可以将其序列化。在遍历的循环中对象的类是无关的,只有序列化的对象的属性是相关的。独立的interface使你只关注对象的某个方面,而不关注其他方面。相比之下,对于功能模块,你要输入的参数,与你手头的想要做的事情无关。原因五,事件应用中,用户界面的鼠标单击,新帐户的建立,都可以触发一个事件,这个事件要被他感兴趣的处理者知道。事件和事件处理与调用过程有相似之处:触发事件就相当于调用子程序,处理事件就相当于被调用子程序的主程序。区别是被调用的子程序和调用程序是帮定的一块儿的,而事件则不同,处理者有可能处理触发的事件,但也不一定。面向过程的ABAP的事件处理是通过运行时来实现的。而在OO中,类和对象既可以触发事件,又可以处理事件。下面将详细讨论这两种模式对事件处理的支持。面向过程的事件处理对于面向过程的ABAPER来说事件的概念可以说是再熟悉不过了。没有事件你就无法执行ABAP程序。要想通过SUBMIT来执行一个程序,那么它必须有个start-of-selection的事件,它是由运行时触发的。对于屏幕处理逻辑,必须能够处理PBO和PAI事件。另外在SELECTION SCREEN中你还可以处理AT SELECTION-SCREEN事件,在LIST中处理AT-LINE-SELECTION事件和AT USER-COMMAND事件。面向过程事件的一个问题便是他的隐含性。除了两个例外外,你无法在程序里触发事件,这两个例外是在逻辑数据库的程序里可以通过P
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 燃气管道接入与分配系统优化方案
- 智能建筑空调系统设计、安装及能源管理服务合同
- 夫妻共同财产分割与离婚诉讼子女抚养费支付合同
- 房屋建筑工程施工现场废料管理与利用方案
- 脑出血护理测试题及答案
- 钢结构全寿命周期管理方案
- 道路工程课程的教学改革与虚拟实践模式
- 农林大学复试真题及答案
- 2025年中级轮胎测评题库及答案
- 4.3.1呼吸道对空气的处理(一)说课稿2023-2024学年人教版生物七年级下册
- 2023中华护理学会团体标准-注射相关感染预防与控制
- 公司数据安全与隐私保护管理制度
- 保洁员职业技能鉴定考试题库及答案
- 《科技创新梦想启航》主题班会
- 商业银行数据要素价值洞察研究白皮书2023
- 造粒塔滑模施工方案
- 2024-2030年中国边境经济合作区行业市场发展分析及经验案例与投资趋势研究报告
- 大决战电影赏析课件
- 中文自修杯汉字小达人第二至八届区级活动真题(答案)
- 中药郁金课件
- 爆破飞石控制措施
评论
0/150
提交评论