
ABAP 事件
一、介绍
事件(Event)在前面已经提及,但在这章会通过实际程序详细介绍。在ABAP对象中 在没有继承关系的类之间,从一个类的方法中调用另一个类的方法时需要使用事件来控制。 在类中定义事件时类的方法可以触发事件,这与 Event Handler 交替启动。[图 14-18]很好地体 现了类C1与C2中的 Event Trigger 与Event Handler 的关系。当用户进行单击鼠标或按(F1) 键等操作时,在ABAP程序画面上可以通过事件进行处理。 在[图14-19]中创建了类C1和C2两个实例。SET HANDLER语句为实例创建透明的处 理器表(E1)。处理器表包含了处理器方法名和已注册的(registered)实例的Reference。表 内的记录根据 SETHANDLER 语句动态管理。即使初始化对象 H1和 H2,只要实例 C2<1>、 C2<2>还存在于处理器表中,就不会被 Garbage Collection删掉。Garbage Collection 收集记忆 装置的无用信息,以便以后程序中重新利用,此外因程序积累太多垃圾数据,导致记忆装置 没有多余空间时会自动执行。
当触发事件时(R1方法在M1中发生事件E1时)系统会从事件表中执行相应实例的方 法。 ① 必须有注册事件的类(C1)。 ② 必须有定义处理器方法的 M2的类(C2)。 ③ 在主程序中有注册处理器方法M2的内容。
二. 触发事件
为了触发事件(EventTrgger),类必须在类声明部分定义事件,使其在方法中触发事件
1.声明事件
在类或接口的声明部分首先声明事件。用以下语句声明实例事件。静态事件使用 CLASS-EVENT 语句。
- 实例事件 用EVENSTS语句可以声明实例事件。只有实例方法才能调用实例Event。
EVENTS evt EXPORTING.. VALUE(el e2 .)
TYPE type [OPTIONAL]...
- 静态事件 可利用CLASS-EVENTS语声明静态事件。所有方法都能调用静态事件。静态事件是 在静态方法中可以调用的唯一事件类型。
CLASS-EVENTS evt...
2.Triggering Event
类内部的实例事件在类的所有实例中都可以触发。静态事件在所有方法中都可以触发 但是只有静态方法才能触发静态事件。
RAISE EVENT evt EXPORTING el = fl e2 = f2 ..
二、 Handling Event
触发事件的前提是方法必须声明为Handler 方法,且执行前要注册事件。
1.声明事件处理器方法(Event Handler Method)
所有类都拥有其他类触发自身类时可以调用的事件处理器方法。当然,可以在同一个类 中用事件和事件处理器定义方法。
METHODS meth FOR EVENT evt OF cifIMPORTING el e2 ...
Static 方法可以用 CLASS-METHODS 语句定义。
2.注册事件处理器方法
若要使事件处理器方法启用事件,执行时需要注册处理器。
SET HANDLER hl h2 . FOR...
指定要注册的实例事件处理器的对象领域时使用FOR语。用FORALLINSTANCES 语句可以一次性注册可触发事件的所有实例处理器。
SET HANDLER hl h2 ... FOR ref.
SET HANDLER h1 h2 ... FOR ALLINSTANCES.MOVE f1+2(3)TO f2.
在静态事件中无法使用FOR语句。
SET HANDLER hl h2 ...
3. Raise Event
调用RAISEEVENT语开始执行下一个阶段之前,执行所有被注册的处理器方法 (Synchronous Eventhandling)。若处理器方法触发的是自身事件,则执行原有的处理器方法 之前,执行自身处理器方法。为了防止发生无限循环,将其控制为只执行64次循环。处理器 方法按照注册的顺序执行。若动态地执行事件处理器,则无法预测其执行顺序。此时只能理 解为同时执行所有事件处理器来进行编码。
4.EVENT 例题
面向对象程序是通过交换对象之间的信息处理数据。继承树中存在的类之间(承关系) 可以调用对方的方法自由的交换信息,但相互独立的类之间需通过事件才能交换信息。此时, 事件的主人(Owner)是注册该事件的类对象,此外所有的类都会注册事件。只有事件的实例 对象才有权限触发事件,其他类只是处于触发事件等待状态(SETHANDLER)。通过[例14-18] 也许容易理解类、方法、事件及事件处理器。为了触发保龄球馆的会员(对象)去打保龄的 事件,需要经过的过程用代码怎么实现呢?请参照[例14-18]。 [结果14-18]
WAIT A MINUATE ~
OK, LETS GO !!!
邻居(类)之间无法直接控制对方的行为,因此通过“去打一场保龄吧”事件可以 影响邻居的行为(Method)。其中,会长职位对应的是类C1,会员是类C2,且会长姓 金,会员姓李。
- EVENTS: BOWL.
会长(小金)为了想让会员打保龄球(BOWL)时打电话而给了他手机号,当会员(小 李)来电话时记录了BOWL名作为联系人名(注册事件)。 - METHODS LETSGO FOR EVENT BOWL OF c1.
会员(小李)的手机里在会长(小金)的手机号上记录了LETSGO名字(注册处理器方 法) - SET HANDLER LEE->LETSGO FOR KIM.
代表会长的类C1才有去打保龄球的事件最终决定权。会员C2为了打保龄球,打会长给 的手机号(SETHANDLER)。这就像小李对小金说:“我已经准备好去打球,你准备好了 再联系我” - RAISE EVENT BWL.
正在睡觉的会长小金收到要去打自己喜欢的保龄球事件后,兴奋的他醒来回复: “首先要准备一下打保龄球的装备,准备完后联系你,稍等一下!”(触发事件)。 - KIM->GO BOWL()或者 CALLMETHOD KIM->GO BOWL( )的缩写
准备完后,会长小金对会员小李说:“准备好了,走吧!” 首先,小金的GOBWL方法触发BOWL事件,然后此事件调用连接在一起的小李的 LETSGO方法。这个过程叫触发(Trigger)。这样,两个人就高兴地去打球了。 为了有助于理解下面按顺序排列了执行事件的过程,在实际程序中按照(例14-19]的顺序 执行。下面练习使用内表。
REPORT z14_19.
TABLES:sflight.
SELECT-OPTIONS: s carrid FOR sflight-carrid.
CLASS CI DEFINITION.
PUBLIC SECTION.
TYPES:BEGIN OF t_sflight,
carrid TYPE sflight-carrid,
connid TYPE sflight-connid,
fldate TYPE sflight-fldate,
END OF t_sflight.
DATA :gt_itab TYPE STANDARD TABLE OF t_sflight,
gs_str TYPE t_sflight.
EVENTS: el .
METHODS : get_data ,display_data ,no_data
FOR EVENT el OF cl.
"C1 DEFINITION
ENDCLASS.
CLASS c1 IMPLEMENTATION.
METHOD: get_data .
SELECT carrid connid fldate FROM sflight
INTO TABLE gt_itab
WHERE carrid IN s_carrid.
IF sy-subrc < O.
RAISE EVENT e1.
ELSE .
CALL METHOD display data .
ENDIF.
ENDMETHOD.
"get_data
METHOD:display_data .
LOOP AT gt_itab INTO gs_str.
WRITE:/10 gs_str-carrid.
WRITE:40 gs_str-connid.
WRITE:60 gs_str-fldate.
ENDLOOP.
"DISPLAY DATA
ENDMETHOD.
METHOD no_data .
WRITE:/10 'There is no data'.
ENDMETHOD.
ENDCLASS.
"no data
"C1 IMPLEMENTATION
DATA : go_obj TYPE REF TO c1.
START-OF-SELECTION.
CREATE OBJECT: obi.
SET HANDLER go obj->no_ data FOR: objl
CALL METHOD go obj->get_data .
[结果 14-19]
AA 0017 2013-12-15
AA 0017 2014-01-12
AA 0017 2014-02-09
AA 0017 2013-03-09
AA 0017 2015-04-06
5.参数说明[例 14-19]
1) 注册处理器方法
SETHANDLER go obj->no data FOR: obj1。obj1 在自己的方法 no data 中注册了处理器 方法。 2) 调用处理器方法
CALL METHOD go obj->get data.
getdata方法是事件e1的处理器方法。
3) 执行方法
执行 get data方法。执行 SQL语句,若没有査询到数据,则触发 RAISE EVENT,若有 数据则调用 display data 方法。
4) 调用事件
若没有查询到数据,则触发事件返回[结果 14-19]。
5) 触发事件
类c1中注册了事件e1,然后声明了自己事件对应的处理器方法。
EVENTS: el .
METHODS:get_data ,display_data ,no_data
FOR EVENT el OF cl.
虽然有三个处理器方法,但只会调用其中的SETHANDLER go_obj->no data FOR: objl 语句中注册的处理器方法nodata。