一、类
类(Class)可看做是对象的骨骼 (Template) 或者对象的类型。另外,类是抽象化对象的明细表。即可以说是制作对象的设计书。对象属性由描述对象的状态和行为的构成要素Component)决定。
比较结构化程序和面向对象程序
例:
*比较结构化程序 和 面向对象程序
DATA :l_file_table TYPE Filetable,
l_rc TYPE i,
l_user_actio TYPE i,
file_name TYPE string.
*结构化程序
CALL FUNCTION 'WS_FILENAME_GET'
EXPORTING
def_filename = ' '
def_path = 'C:\'
title = 'FILE OPEN'
IMPORTING
filename = file_name
rc = l_rc.
*面向对象程序
CALL METHOD cl_gui_frontend_services=>file_open_dialog
EXPORTING
window_title = 'File Open'
default_filename = space
file_filter = '*.xls'
initial_directory = 'C:\'
multiselection = space
CHANGING
file_table = l_file_table
rc = l_rc
EXCEPTIONS
file_open_dialog_failed = 1
cntl_error = 2
error_no_gui = 3
OTHERS = 5.
类中值的传递:exporting和improting
*类中值的传递
CLASS cl DEFINITION. "定义类
PUBLIC SECTION.
DATA: l_char TYPE char20.
METHODS : set_data IMPORTING p_imp TYPE char20, "此处的importing表示入参
get_data EXPORTING p_exp TYPE char20. "此处的exporting表示出参
ENDCLASS.
CLASS cl IMPLEMENTATION. "定义类的方法
METHOD set_data.
l_char = p_imp.
ENDMETHOD.
METHOD get_data.
p_exp = l_char.
ENDMETHOD.
ENDCLASS.
DATA: go_cref TYPE REF TO cl, "引用类
gv_data TYPE char20.
START-OF-SELECTION.
CREATE OBJECT go_cref. "实例化对象
CALL METHOD go_cref->set_data
EXPORTING " 输入参数 将‘test class method’ 赋值给p_imp 然后执行set_data方法,将p_imp赋值给变量l_char。
p_imp = 'test class method'.
CALL METHOD go_cref->get_data
IMPORTING "参数输出 执行get_data方法 将l_char赋值给p_exp 然后p_ezp 赋值给gv_data
p_exp = gv_data.
WRITE gv_data.
1、构成要素:
类中存在两种构成要素。一种是各个类的对象中都存在的,另一种与实例数无关,整个类就存在一个。前者是实例-specific 项目,叫做实例 Component (实例组件)。该项目是参照类创建对象时,内存中存在的项目,每每创建对象时都会被初始化。后者是 Non 实例specific 项目,也叫作静态组件。该项目从遇到创建类的语句 (CREATE OBJECT 语)开始,直到程序结束都存储于内存中,是依赖类存在的项目。Static 属性用 CLASS-DATA 语句声明,Static 方法用 CLASS-METHOD 方法声明。Static 属性和方法是为了制作类组件而声明的,即使不创建对象,若已存在于内存中即可以直接使用。
(1)属性:
属性(Attribute可以拥有 ABAP 所有数据类型的类内部数据字段。对象状态由属性的内容决定。属性的一种类型是 Reference Variable。Reference Variable 可以创建对象及指定地址。Reference Variable 可在类内部定义,并且使它从类内部访问对象。
(2)方法:
方法用来定义决定对象行为的类内部执行步骤。方法可以访问类的所有属性,且可通过方法修改对象内容。另外,还提供传入传出参数,便于用户交互。在这方面类似于 FunctionModule。类的 PRIVATE 属性只能通过同一类的方法进行修改。在类声明(DEFINTION)部分,利用 METHOD 语句定义,在IMPLEMNT 部分记载方法的功能。
(3)事件:
事件是没有继承关系的类之间可以相互调用彼此方法的特殊方法。对象(或者类)为了调用其他对象(或者类的事件控制方法时需要使用事件(事件控制方法也是一种方法。)
(4)访问权限区域:
(1) PUBLIC SECTION
在PUBLIC SECTION 访问权限下定义项目,则在所有类中都可以访问。PUBLIC 类的组件(=成员,项目) 构成类与用户之间的接口。
(2) PROTECTED SECTION
在 PROTECTED 访问权限下定义的项目,只有自己和继承类才能访问,且充当继承类之间的接口。
(3) PRIVATE SECTION
在 PRIVATE 访问权限下定义的项目,只显示在相同类的方法中。在外部区域中无法访问,封装在内部类中。IMPLEMENTATION 部分的所有方法在类中都可以访问,没有任何限制。
例1:
*利用类定义继承关系了解访问修饰符
CLASS c1 DEFINITION.
PROTECTED SECTION. "若此处是private访问修饰符,将不能被c2继承。会报错
DATA: l_num TYPE i.
ENDCLASS.
CLASS c2 DEFINITION INHERITING FROM c1. "c2继承c1
PUBLIC SECTION.
METHODS :set_data IMPORTING p_imp TYPE i,
get_data EXPORTING p_exp TYPE i.
ENDCLASS.
CLASS c2 IMPLEMENTATION.
METHOD set_data.
l_num = p_imp.
ENDMETHOD.
METHOD get_data.
p_exp = l_num + 1.
ENDMETHOD.
ENDCLASS.
DATA:go_cref TYPE REF TO c2.
DATA:gv_data TYPE i.
START-OF-SELECTION.
CREATE OBJECT go_cref.
CALL METHOD go_cref->set_data
EXPORTING
p_imp = '10'.
CALL METHOD go_cref->get_data
IMPORTING
p_exp = gv_data.
WRITE: / gv_data.
*访问权限示例
CLASS cl DEFINITION.
PUBLIC SECTION.
METHODS: set_data IMPORTING p_imp TYPE i,
get_data EXPORTING p_exp TYPE i.
* PROTECTED SECTION. "删掉注释会报错
DATA: l_num TYPE i.
ENDCLASS.
CLASS cl IMPLEMENTATION.
METHOD set_data.
l_num = p_imp.
ENDMETHOD.
METHOD get_data.
p_exp = l_num + 1.
ENDMETHOD.
ENDCLASS.
DATA: go_cref TYPE REF TO cl.
DATA:gv_data TYPE i.
START-OF-SELECTION.
CREATE OBJECT go_cref.
CALL METHOD go_cref->set_data
EXPORTING
p_imp = '10'.
WRITE: 'set_data method:',go_cref->l_num.
CALL METHOD go_cref->get_data
IMPORTING
p_exp = gv_data.
WRITE: / 'get_data meth
二、对象
- 参照对象:
参照对象变量可以参照或初始化已经存在的对象。指向对象的参照变量清楚对象的实体,类的实例可以利用指向对象的参照变量指定地址。利用参照对象变量的对象不能直接使用对象的构成要素,需利用 Reference (对象地址)。ABAP 中已经存在类似于结构体或者内表中使用的数据类型,也已经定义了参照变量中使用的数据类型。分别是 Class Reference 和Interface Reference。
例:
*分配参照对象
CLASS cls DEFINITION INHERITING FROM object.
PUBLIC SECTION.
METHODS:create.
ENDCLASS.
CLASS cls IMPLEMENTATION.
METHOD create.
WRITE: / 'object created'.
ENDMETHOD.
ENDCLASS.
DATA: go_cref1 TYPE REF TO cls.
DATA: go_cref2 TYPE REF TO cls.
START-OF-SELECTION.
CREATE OBJECT go_cref1.
go_cref2 = go_cref1. "等价于 move go_cref1 to go_cref2
CALL METHOD:go_cref2->create.
2、创建对象:
利用此参照变量创建类的实例-对象。若参照对象变量在程序声明部分已经参照了对象,创建实例即对象时不用重复使用 TYPE语句。
例:
*创建一个简单的ABAP面向对象程序
CLASS cl DEFINITION.
PUBLIC SECTION.
METHODS meth.
ENDCLASS.
CLASS cl IMPLEMENTATION.
METHOD meth.
WRITE / 'CALSS TEST'.
ENDMETHOD.
ENDCLASS.
DATA : go_cref TYPE REF TO cl.
START-OF-SELECTION.
CREATE OBJECT go_cref.
CALL METHOD go_cref->meth.
3、访问对象组件:
为了访问对象的属性和方法,使用 ref->attr 或者 CALL METHOD ref->meth 语句。ref->meth 语句是 CALL METHOD refmeth语句的缩写
4、在类中创建多个实例
(1)分配参照对象
可以通过 MOVE 语句为其他参照对象分配值。连接在同一个个体的参照变量之间可以创建引用。使用 MOVE 语句或分配符号“=”时系统会自动检查是否为可以分配的类型。
(2)CASTING:
可以利用 casting 符号“?”参照从其他类衍生的对象创建新对象。此时,其他类指的是父类和从父类继承的子类。子类可重新定义,或追加父类的属性及方法。从父类衍生的对象和子类衍生的对象类型可能不同,但此时可用 casting 符号“?”正常执行程序。
例:
*casting 用法
CLASS vehicle DEFINITION INHERITING FROM object.
PUBLIC SECTION.
METHODS: create,drive.
PROTECTED SECTION.
DATA speed TYPE i VALUE '100'.
ENDCLASS.
CLASS plane DEFINITION INHERITING FROM vehicle.
PUBLIC SECTION.
METHODS: fly.
ENDCLASS.
CLASS vehicle IMPLEMENTATION.
METHOD create.
WRITE / 'created method.'.
ENDMETHOD.
METHOD drive.
speed = speed + 100.
WRITE : 'drive is possible,','current speed:',speed.
ENDMETHOD.
ENDCLASS.
CLASS plane IMPLEMENTATION.
METHOD fly.
speed = speed + 1000.
ENDMETHOD.
ENDCLASS.
DATA:car TYPE REF TO vehicle,
air TYPE REF TO vehicle.
START-OF-SELECTION.
CREATE OBJECT car.
air ?= car. " 参照父类或从父类继承的子类对象,创建新的对象
CALL METHOD air->drive.
CALL METHOD air->create.
* CALL METHOD air->fly. “报错,无法调用fly方法
三、方法
1、声明方法:
2、实现方法:
在类中声明的方法需在IMPLEMENTATION 部分实现其功能 (IMPLEMENTATION 或
者Implement 指的是要实现方法的功能)。
实现方法时不必定义类方法声明部分以外的接口参数。接口参数充当局部变量的角色,因此在方法内可以利用DATA语句定义局部变量。和功能模块相同,可以利用RAISE exception和MESSAGE RAISING 语句处理错误。使用 Static 方法时要记住,其只适用于类的静态属性。
3、调用方法:
在方法内调用其他方法时使用如 CALL METHOD meth.这样的语句即可。在类外部调用方法时使用 CALL METHOD ref>meth 语句。Ref包含指向类接口值的参照对象变量。调用方法时必须要定义类似 EXPORTING 或者 CHANGING 语句。但 IMPORTING 或者RECEIVING 及处理错误的 EXCEPTIONS 语句是可选项,必要时使用即可。
4、调用动态方法:
例:
*动态调用对象方法
CLASS c1 DEFINITION.
PUBLIC SECTION.
DATA: gt_itab TYPE TABLE OF sflight,
gs_str TYPE sflight.
METHODS:get_data,wri_data.
ENDCLASS.
CLASS c1 IMPLEMENTATION.
METHOD:get_data.
SELECT * INTO TABLE gt_itab FROM sflight
UP TO 5 ROWS.
ENDMETHOD.
METHOD:wri_data.
LOOP AT gt_itab INTO gs_str.
WRITE: / gs_str-carrid,gs_str-connid.
ENDLOOP.
ENDMETHOD.
ENDCLASS.
DATA go_ref TYPE REF TO c1.
DATA gv_mth TYPE string.
FIELD-SYMBOLS <fs> TYPE any.
START-OF-SELECTION.
CREATE OBJECT go_ref.
gv_mth = 'GET_DATA'.
CALL METHOD go_ref->(gv_mth).
gv_mth = 'WRI_DATA'.
CALL METHOD go_ref->(gv_mth).
动态分配属性:
*动态属性分配
CLASS c1 DEFINITION.
PUBLIC SECTION.
DATA : gt_itab TYPE TABLE OF sflight,
gs_str TYPE sflight.
METHODS: get_data.
ENDCLASS.
CLASS c1 IMPLEMENTATION.
METHOD:get_data.
SELECT * INTO TABLE gt_itab
FROM sflight UP TO 5 ROWS.
ENDMETHOD.
ENDCLASS.
DATA go_ref TYPE REF TO c1.
DATA gv_mth TYPE string.
DATA gv_attr TYPE string.
FIELD-SYMBOLS <fs1> TYPE STANDARD TABLE. "标准表
FIELD-SYMBOLS <fs2> TYPE any. "任意变量/结构
FIELD-SYMBOLS <fs3> TYPE any.
START-OF-SELECTION.
CREATE OBJECT go_ref.
gv_mth = 'GET_DATA'.
CALL METHOD go_ref->(gv_mth).
gv_attr = 'GT_ITAB'.
ASSIGN go_ref->(gv_attr) TO <fs1>. "fs1 指向 c1 类的gt_itab属性
LOOP AT <fs1> ASSIGNING <fs2>.
DO.
ASSIGN COMPONENT sy-index OF STRUCTURE <fs2> to <fs3>. "通过字段号分配
WRITE: <fs3>.
IF sy-subrc NE 0.
EXIT.
ENDIF.
ENDDO.
WRITE : / .
ENDLOOP.
5、事件处理方法:
事件处理方法 (Event Handler Method)是无法用 CALL METHOD 调用的特殊类型的方法。 该方法不用 CALL METHOD,而是使用事件。为了用事件处理方法定义方法,需在 METHODS 或者 CLASS-METHODS 部分追加如下语句。
6、构造函数:
构造函数(Constructor)也是无法用 CALL METHOD 调用的特殊函数。然而,当指定或者新对象的初始值时,在 Runtime 环境下会自动被系统调用。该函数有两种类型,分别实例构造函数和静态构造函数。实例构造函数通过 CREATE OBJECT 语句,每次创建接口都调用;而静态构造函数只在一开始调用类时被调用一次。
例:
*构造函数
CLASS c1 DEFINITION.
PUBLIC SECTION.
DATA: gt_itab TYPE TABLE OF sflight,
gs_str TYPE sflight.
DATA: gv_carrid TYPE s_carr_id,
gv_connid TYPE s_conn_id.
METHODS: constructor IMPORTING i_carrid TYPE s_carr_id "构造方法
i_connid TYPE s_conn_id.
METHODS:get_data.
ENDCLASS.
CLASS c1 IMPLEMENTATION.
METHOD:constructor.
gv_carrid = i_carrid.
gv_connid = i_connid.
ENDMETHOD.
METHOD:get_data.
SELECT * INTO TABLE gt_itab
FROM sflight
WHERE carrid = gv_carrid
AND connid = gv_connid.
ENDMETHOD.
ENDCLASS.
DATA:go_ref TYPE REF TO c1.
START-OF-SELECTION.
CREATE OBJECT go_ref "构造方法。创建对象的时候自动调用
EXPORTING
i_carrid = 'AZ'
i_connid = '0555'.
CALL METHOD go_ref->get_data.
LOOP AT go_ref->gt_itab INTO go_ref->gs_str.
WRITE : / go_ref->gs_str-carrid, go_ref->gs_str-connid,go_ref->gs_str-fldate.
ENDLOOP.
四、继承
继承(Inheritance)是使类之间拥有共同的属性及方法的功能。一个类通过分析过程衍生为更详细且精制的子类,此时子类会继承父类的属性及方法。使用继承的根本原因在于类的重复利用。
在子类中不用附加声明属性和方法。但是子类可以访问超级类的 PUBLIC、PROTECTED组件。子类中虽然存在超级类的 PRIVATE 组件,但也需要以相同的名字再次定义。从超级类继承的子类方法可以访问超级类的 PRIVATE 属性。
1、重新定义方法
连接在子类中的所有参照变量可使用重新定义的方法。即使 Reference 参照超级类也会调用重新定义的方法。在重新定义的方法内,可以使用 super-> 语句访问原有的超级类中的方法。这样可以使子类免去重复编码直接使用超级类的方法。
例:
*重定义方法、调用父类原有的method
CLASS c1 DEFINITION INHERITING FROM object.
PUBLIC SECTION.
METHODS:create.
ENDCLASS.
CLASS c1 IMPLEMENTATION.
METHOD create.
WRITE: / 'Original method is called'.
ENDMETHOD.
ENDCLASS.
CLASS c2 DEFINITION INHERITING FROM c1.
PUBLIC SECTION.
METHODS:create REDEFINITION. "重定义create方法
ENDCLASS.
CLASS c2 IMPLEMENTATION.
METHOD create.
CALL METHOD super->create. "调用父类的create方法
WRITE: / 'methid is redefined'.
ENDMETHOD.
ENDCLASS.
DATA: go_obj TYPE REF TO c2.
START-OF-SELECTION.
CREATE OBJECT go_obj.
CALL METHOD go_obj->create.
2、继承与参照变量
Class3 是 Class2 的子类,Class2 又是Class1 的子类。即右侧的对象都是 Class1 的实例。类的参照变量 Cref1、2、3 分别在参照 Class1、2、3 且都与对象连接在一起。但是只有 Cref1 才能指定 Class1的PUBLIC 组件地址。Cref2 可以指定 Class1 和 Class 2的PUBLIC 组件地址。Cref3 可以指定所有类的 PUBLIC 组件地址。
3、抽象/最终方法和类
ABSTRACT 和 FINAL 语使用方法和类定义抽象、最终方法和类。抽象方法定义在抽象类中,但在类中无法实现功能,不过可以在类的子类中实现。抽象类无法初始化创建。Abstract 类不能用初始化创建。
4、类的构成要素和命名空间
这种超级类的组件中只显示 PUBLIC 和 PROTECTED 属性。所有 PUBLIC、PROTECTED 组件包含在继承树中,且属于同一个命名空间里。综上所述,存在于继承树上的组件都拥有唯一的名字。相反PRIVATE 组件却只在所属类中有唯一的名字。
重新定义方法时,将相同名字的方法重新 IMPLEMENTATION 覆盖超级类的方法。但是重新定义的方法却无法替代原有的方法 IMPLEMENTATION。这是因为原超级类的方法名字已经以唯一的名字保留。前面已经提到,不是调用子类中重新定义的方法,而是调用超级类的原有方法时要使用 super-> 语句。这种符号称为 Pseudo Reference。
5、继承与静态属性
与类的所有构成要素一样,静态属性在各个继承树上只存在一个。子类可以访问超级类的 PUBLIC 和 PROTECTED 静态属性。相反,超级类可以与子类共享自己的 PUBLIC、PROTECTED 属性。在前面已经介绍,静态属性用 CLASS-DATA 语定义,而静态方法用CLASS-METHOD 语句定义。下面通过练习再仔细观察关于静态属性和方法。静态属性和方法是为了制作类的组件而定义的,即使不创建对象也会显示在内存中。即使创建对象使用静态属性和方法也不会发生错误,但不建议采用此法。
6、继承和构造函数
(1)实例构造函数:
所有类都拥有实例构造函数,调用创建对象的构造函数时使用。前面提到,在继承树上的组件名字必须唯一,而构造函数却是例外事项。但是要谨记,这些类的实例构造函数在继承树上保持着完全独立的关系。
在子类中不能重新定义超级类的实例构造函数,也不能使用CALL METHOD 构造函数语句。若使用此语句会生没有这个名字的错误信息。创建对象时系统会自动调用此函数。若子类包含超级类的 Visible 属性,则子类的实例构造函数可以调用超级类的实例构造函数。每个子类实例创建者需包含 CALLMEOTHD SUPER->Constructor语句。没有明确声明实例构造函数的超级类会默认调用实例构造函数。没有明确定义实例创建者的超级类会默认调用实例创建者。依此自动调用超级类的实例创建者。调用默认构造函数时有多个参数可供选择。
(2)静态构造函数:
所有类都包含了 class_constructor 静态构造函数。此方法在系统中已经存在,且使用类自身方法之前被调用,另外也没有参数。若在程序中已经指定子类地址(创建对象),则静态构造函数处于已执行状态。但执行子类静态构造函数之前必须执行所有超级类的静态构造函数。此函数在程序中只能调用一次。
五、接口
比较类和抽象类
一般类可以通过初始化来创建对象 (CREATE OBJECT),但是抽象类不可以,只能从子类继承使用。因为抽象类没有实现功能的IMPLEMENTATION 部分。抽象类是将一些共通的功能集合在一个类中,然后继承此类在子类中使用
比较类和接口
接口,如抽象类,不能直接通过初始化使用。然而可以追加到类中实现IMPLEMENTATION。类要实现接口的功能,只能通过接口实现。
比较抽象类和接口
抽象类是在子类继承后才能实现自己具备的方法功能,而 ABAP 对象中只能单一继承,因此继承抽象类的子类不能再继承其他类。但是接口不属于继承,是在类中追加声明的概念因此可以多重继承。
1、定义接口
接口如同类,在 ABAP 程序中也可定义全局 (Global) 或局部 (Local) 接口。定义部分可以包含属性、方法、事件等所有项目。接口组件不必定义在访问权限领域中,是因为在类中追加接口时必须定义在 PUBLIC SECTION 中。另外在类中实现接口的方法,因此接口不能包含功能实现部分。
2、实现接口
在类中接口只能定义在 PUBLIC SECTION 中,因此实现接口的方法功能时,接口的组件会追加到类的 PUBLIC SECTION 中。换言之,上语句中接口 intf 的组件 meth 定义在类的IMPLEMENTATION 中,则类中会存在 intf-meth。如右上图语句所示,接口的方法可以在类中实现,即接口可以在其他类中实现其功能。
3、参照接口
参照变量可以访问对象。不用创建参照类的参照变量,只需定义参照接口的参照变量就可以访问对象。即若类中已经实现了接口 intf,则只用参照接口的参照变量就可以访问组件,意味着不必创建类的参照变量。
接口通过 Reference 可以使多个类拥有统一形态。这称为多态性(Polymorphism)
例:
* 接口
INTERFACE account. "定义接口
METHODS calc.
DATA balance TYPE i.
ENDINTERFACE.
CLASS c1 DEFINITION.
PUBLIC SECTION.
INTERFACES account. "实现接口
ENDCLASS.
CLASS c1 IMPLEMENTATION.
METHOD account~calc. "重写接口的方法
WRITE : / 'deposit money is :',account~balance.
ENDMETHOD.
ENDCLASS.
CLASS c2 DEFINITION.
PUBLIC SECTION.
INTERFACES account. "实现接口
ENDCLASS.
CLASS c2 IMPLEMENTATION.
METHOD account~calc. "重写接口的方法
WRITE: / 'withdrawl money id :',account~balance.
ENDMETHOD.
ENDCLASS.
DATA:ref1 TYPE REF TO c1,
ref2 TYPE REF TO c2,
iref TYPE REF TO account.
START-OF-SELECTION.
create OBJECT:ref1,ref2.
ref1->account~balance = 300. "赋值
CALL METHOD: ref1->account~calc. "从ref1调用接口的方法
iref = ref1. "接口参照ref1的属性和方法
CALL METHOD iref->calc. "接口参照ref1调用方法calc
ref2->account~balance = '-200'. "赋值
CALL METHOD: ref2->account~calc. "从ref1调用接口的方法
iref = ref2. "接口参照ref2的属性和方法
call METHOD iref->calc. "接口参照ref2调用方法calc
4、使用别名
所有接口组件可以利用ALIAS 指定其别名 (Alias Name)。在接口内再调用其他接口的Deep 组件经常使用。ALIAS 只能在接口内或者类的定义部分使用,不能在实现方法功能的ATION 中使用。
例:
*使用别名
INTERFACE account.
METHODS calc IMPORTING p1 TYPE i.
ENDINTERFACE.
CLASS c1 DEFINITION.
PUBLIC SECTION.
INTERFACES account.
ALIASES calc FOR account~calc. "使用别名,方便调用
ENDCLASS.
CLASS c1 IMPLEMENTATION.
METHOD account~calc.
WRITE : / 'deposit money is :',p1.
ENDMETHOD.
ENDCLASS.
DATA:ref TYPE REF TO c1.
START-OF-SELECTION.
CREATE OBJECT:ref.
CALL METHOD:ref->calc EXPORTING p1 = 200. "使用别名调用
六、事件
在 ABAP 对象中在没有继承关系的类之间,从一个类的方法中调用另一个类的方法时需要使用事件来控制。在类中定义事件时类的方法可以触发事件,这与 Event Handler 交替启动。
1、触发事件
(1)声明事件
在类或接口的声明部分首先声明事件。用以下语句声明实例事件。静态事件使用
CLASS-EVENT 语句。
1)实例事件:
2)静态事件:
可利用 CLASS-EVENTS 语声明静态事件。所有方法都能调用静态事件。静态事件是在静态方法中可以调用的唯一事件类型。
(2)Triggering Event
类内部的实例事件在类的所有实例中都可以触发。静态事件在所有方法中都可以触发但是只有静态方法才能触发静态事件。
2、Handing Event
(1)声明事件处理器方法(Event Handing Method)
(2)注册事件处理器方法
在静态事件中无法使用 FOR 语句。
(3)Raise Event
调用 RAISE EVENT 语句开始执行下一个阶段之前,执行所有被注册的处理器方法(Synchronous Event handling)。若处理器方法触发的是自身事件,则执行原有的处理器方法之前,执行自身处理器方法。为了防止发生无限循环,将其控制为只执行 64 次循环。处理器方法按照注册的顺序执行。若动态地执行事件处理器,则无法预测其执行顺序。此时只能理解为同时执行所有事件处理器来进行编码。