[SAP ABAP开发技术总结]面向对象OO

由于历史遗留原因,很多项目也还在使用老的ABAP过程化语句进行开发,但新的SAP很多的东西都已经通过类来实现了,比如BAPI(比类还早)、BADI、ALV,还有很多东西都了已经通过类来重写了,所以为了与时俱进,还是使用类吧

2.   面向对象

2.1.  类与接口定义

CLASS class DEFINITION [ABSTRACT][FINAL].
  [
PUBLIC SECTION.
    [
components]]
  [
PROTECTED SECTION.
    [
components]]
  [
PRIVATE SECTION.
    [
components]]
ENDCLASS.

INTERFACE intf.
  [
components]
ENDINTERFACE.

2.1.1.   components

2  TYPES, DATA, CLASS-DATA, CONSTANTS  for data types and data objects

2  METHODS, CLASS-METHODS, EVENTS, CLASS-EVENTS for methods and events

2  INTERFACES如果在类中,表示需要实现哪个接口;如果是在接口中,表示继承哪个接口 for implementing interfaces

2  ALIASES  for alias names for interface components给接口组件取别名

2.2.  类定义、实现

CLASS math DEFINITION.
 
PUBLIC SECTION.
   
METHODS divide_1_by
           
IMPORTING operand TYPE i
           
EXPORTING result  TYPE f
           
RAISING cx_sy_arithmetic_error.
ENDCLASS.
CLASS
math IMPLEMENTATION.
 
METHOD divide_1_by.
    result
= 1 / operand.
 
ENDMETHOD.
ENDCLASS.

2.3.  接口定义、实现

INTERFACEint1.

ENDINTERFACE.

CLASSclass DEFINITION.                        [?defi?ni??n]
    PUBLICSECTION.
      
INTERFACES: int1,int2."
实现多个接口
ENDCLASS.

CLASS class IMPLEMENTATION.                     [??mpl?m?n?te?-??n]
   
METHOD
intf1~imeth1
.
    ENDMETHOD.
ENDCLASS.

2.4.  类、接口继承

CLASS<subclass> DEFINITIONINHERITINGFROM<superclass>.[in?herit]

 

INTERFACE i0.
 
METHODS m0.
ENDINTERFACE
.
INTERFACE i1.
 
INTERFACES i0.
 
"可以有相同的成员名因为继承过来后成员还是具有各自的命名空间在实现时
 
"被继承过来的叫 i0~m0这里的名为i1~m0所以是不同的两个方法
 
METHODS m0.
 
METHODS m1.
ENDINTERFACE.

2.5.  向下强转型?=

CLASS person DEFINITION.

ENDCLASS.

CLASS stud DEFINITION INHERITING FROMperson.

ENDCLASS.

 

START-OF-SELECTION.

  DATA p TYPE REF TO person.

  DATA s TYPE REF TO stud.

  CREATE OBJECT s.

  p = s. "向上自动转型

  "拿开注释运行时抛异常,因为P此时指向的对象不是Student,而是Person所以能强转的前提是P指向的是Student

  "CREATE OBJECT p.

  s ?= p."向下强转型

2.6.  方法

METHODS/CLASS-METHODS meth [ABSTRACT|FINAL]
    [
IMPORTING parameters [PREFERRED PARAMETER
p]]
    [
EXPORTING
 parameters]
    [
CHANGING parameters
]
    [{
RAISING|EXCEPTIONS} exc1 exc2 ...]
.

应该还有一个Returning选项,RETURNING不能与EXPORTINGCHANGING同时使用

image034

2.6.1.   parameters

... { VALUE(p1) | REFERENCE(p1) | p1 }
{
TYPE generic_type }
|{TYPE{[LINE OF]
complete_type}|{REF TO {data|object|complete_type |class|intf}}}
|{LIKE{[LINE OF] dobj}|{REF TO dobj} }
[OPTIONAL|{DEFAULT def1}]
     { VALUE(p2) | REFERENCE(p2) | p2 }...

2  dataobject表示是通用数据类型dataobject

2  complete_type为完全限定类型

2  OPTIONALDEFAULT两个选项不能同时使用且对于EXPORTING类型的输入参数不能使用

2  如果参数名p1前没有使用VALUEREFERENCE默认为还是REFERENCE即引用传递

2  方法中的输入输出参数是否能修改请参考FormFunction参数的传值传址

2.6.2.   PREFERRED PARAMETER首选参数

设置多个IMPORTING类型参数中的某一个参数为首选参数。

首选参数的意义在于:当所有IMPORTING类型都为可选optional时,我们可以通过PREFERRED PARAMETER选项来指定某一个可选输入参数为首选参数,则在以下简单方式调用时:[CALL METHOD] meth( a ). 实参a的值就会传递给设置的首选参数,而其他不是首参数的可选输入参数则留空或使用DEFAULT设置的默认值

注:此选项只能用于IMPORTING类型的参数;如果有必选的IMPORTING输入参数,则没有意义了

2.6.3.   普通调用

[CALL METHOD]  meth|me->meth|oref->meth|super->meth|class=>meth[(]

[EXPORTING  p1 = a1 p2 = a2 ...]

{ {[IMPORTING  p1=a1 p2=a2 ...][CHANGING p1 = a1 p2 = a2 ...]}

|[RECEIVING  r  = a  ] }RECEIVING不能与EXPORTINGCHANGING同时使用

[EXCEPTIONS [exc1 = n1 exc2 = n2 ...]

[OTHERS = n_others] ] [)].

如果省略CALL METHOD,则一定要加上括号形式如果通过CALL METHOD来调用,则括号可加可不加

RECEIVING:用来接收METHODS /CLASS-METHODS RETURNING选项返回的值

如果EXPORTINGIMPORTINGCHANGINGRECEIVINGEXCEPTIONSOTHERS同时出现时,应该按此顺序来编写

使用此种方式调用(使用 EXPORTINGIMPORTING等这些选项)时,如果原方法声明时带了返回值RETURNING,只能使用RECEIVING来接受,而不能使用等号来接收返回值,下面用法是错误的:

num2 = o1->m1( EXPORTING p1 = num1 ).

2.6.4.   简单调用

此方式下输入的参数都只能是IMPORTING类型的参数,如果要传CHANGINGEXPORTINGRAISINGEXCEPTIONS类型的参数时,只能使用上面通用调用方式

2  meth( )

此种方式仅适用于没有输入参数IMPORTING输入\输出参数CHANGING或者有但都是可选的、或者不是可选时但有默认值也可

2  meth( a )

此种方式仅适用于只有一个必选输入参数IMPORTING)(如果还有其他输入参数,则其他都为可选,或者不是可选时但有默认值也可),或者是有多个可选输入参数IMPORTING)(此时没有必选输入参数情况下)的情况下但方法声明时通过使用PREFERRED PARAMETER选项指定了其中某个可选参数为首选参数(首选参数即在使用meth( a )方式传递一个参数进行调用时,通过实参a传递给设置为首选的参数

2  meth( p1 = a1 p2 = a2 ... )

此种方式适用于有多个必选的输入参数IMPORTING)方法的调用(其它如CHANGINGEXPORTING没有,或者有但可选),如果输入参数(IMPORTING)为可选,则也可以不必传

2.6.5.   函数方法

Return唯一返回值

METHODS meth
    [IMPORTING
parameters
[PREFERRED PARAMETER p]]
    RETURNINGVALUE(r) typing
    [{RAISING|EXCEPTIONS} exc1 exc2 ...].

 

RETURNING 用来替换EXPORTINGCHANGING不能同时使用。定义了一个形式参数 r 来接收返回值并且只能是值传递

具有唯一返回值的函数方法可以直接用在以下语句中逻辑表达式IFELSEIFWHILECHECKWAITCASELOOP、算术表达式、赋值语句

函数方法可以采用上面简单调用方式来调用meth( )meth( a )meth( p1 = a1 P2 = a2 ... )

 

  ref->m( RECEIVING  r = i ).
 
CALL METHOD ref->m( RECEIVING r = i ).
 
CALL METHOD ref->m RECEIVING r = i.

2.7.  mesuper

等效于Java中的 thissuper

2.8.  事件

2.8.1.   事件定义

EVENTS|CLASS-EVENTS evt [EXPORTING VALUE(p1)
{ TYPE generic_type }
|{TYPE {[LINE OF] complete_type}
|
{ REF TO{data|object|complete_type|class|intf}} }
| {LIKE{[LINE OF] dobj} | {REF TO dobj} }
[OPTIONAL|{DEFAULT def1}]

VALUE(p2) ...].

2  dataobject:表示是通用数据类型dataobject

2  complete_type:为完全限定类型

2  OPTIONALDEFAULT两个选项不能同时使用

2  EXPORTING:定义了事件的输出参数,并且事件定义时只能有输出参数,且只能是传值

 

非静态事件声明中除了明确使用EXPORTING定义的输出外,每个实例事件其实还有一个隐含的输出参数sender,它指向了事件源对象,当使用RAISE EVENT语句触发一个事件时,事件源的对象就会分配给这个sender引用,但是静态事件没有隐含参数sender

 

事件evt的定义也是接口定义部分进行定义的

非静态事件只能在非静态方法中触发,而不能在静态方法中触发;而静态事件即可在静态也可在非静态方法中进行触发,或者反过来说:实例方法既可触发静态事件,也可触发非静态事件,但静态方法就只能触发静态事件

2.8.2.   事件触发

RAISE EVENT evt [EXPORTING p1 = a1 p2 = a2 ...].

该语句只能在定义evt事件的同一类或子类或接口实现方法中进行调用

 

当实例事件触发时如果在event handler事件处理器声明语句中指定了形式参数sender则会自动接收事件源但不能在RAISE EVENT …EXPORTING语句中明确指定它会自动传递(如果是静态事件,则不会传递sender参数)

CLASS c1 DEFINITION.
 
PUBLIC SECTION
.
      EVENTS e1 EXPORTING value(p1) TYPE string value(p2) TYPE i OPTIONAL. "定义
   
METHODS m1.
ENDCLASS.
CLASS c1 IMPLEMENTATION.
 
METHOD m1.

    
RAISE EVENT e1 EXPORTING p1 = '...'."触发
 
ENDMETHOD.
ENDCLASS.

2.8.3.   事件处理器Event Handler

静态或非静态事件处理方法都可以处理静态或非静态事件,与事件的静态与否没有直接的关系

INTERFACE window. "窗口事件接口
 
EVENTS: minimize EXPORTINGVALUE(status) TYPE i."最小化事件
ENDINTERFACE.

CLASS dialog_window DEFINITION. "
窗口事件实现
 PUBLIC SECTION.
  INTERFACES window.
ENDCLASS.

INTERFACE window_handler. "
窗口事件处理器接口

  METHODS: minimize_window 
FOR EVENT window~minimize OF dialog_window
                           
IMPORTING status sender. "
事件处理器方法参数要与事件接口定义中的一致
ENDINTERFACE.

2.8.4.   注册事件处理

实例事件处理器(方法)注册(注:被注册的方法只能是用来处理非静态事件的方法):

SET HANDLER handler1 handler2 ... FOR oref|{ALL INSTANCES}[ACTIVATION act].

静态事件处理器(方法)注册(注:被注册的方法只能是用来处理静态事件的方法):

SET HANDLER handler1 handler2 ... [ACTIVATION act].

oref:只将事件处理方法handler1 handler2注册到 oref 这一个事件源对象

ALL INSTANCES:将事件处理方法注册到所有的事件源实例中

ACTIVATION act:表示是注册还是注销

2.8.5.   示例

CLASS c1 DEFINITION."事件源
 
PUBLIC SECTION.
   
EVENTS: e1 EXPORTING value(p1) TYPE c,e2.
   
CLASS-EVENTS ce1 EXPORTING value(p2) TYPE i.
   
METHODS:trigger."事件触发方法
ENDCLASS.

CLASS  c1 IMPLEMENTATION.
 
METHOD trigger.
   
RAISE EVENT: e1 EXPORTING p1 = 'A',e2,ce1 EXPORTING p2 = 1.
 
ENDMETHOD.
ENDCLASS.

静态(如下面的h1方法)或非静(如下面的h2方法)态事件处理方法都可以处理静态或非静态事件,事件的处理方法是否只能处理静态的还是非静态事件事件的静态与否没有关系,但事件的触发方法事件的静态与否有关系实例方法既可触发静态事件,也可触发非静态事件,但静态方法就只能触发静态事件);但是,事件处理方法虽然能处理的事件与事件的静态与否没有关系,但如果处理的是静态事件,那此处理方法就成为了静态处理器,只能采用静态注册方式对此处理方法进行注册。如果处理的是非静态事件,那此处理方法就是非静态处理器,只能采用非静态注册方式对此处理方法进行注册

处理器的静态与否与处理方法本身是否静态没有关系,只与处理的事件是否静态有关


CLASS c2 DEFINITION."监听器即事件处理器
 
PUBLIC SECTION.
   
"
静态方法也可以处理非静态事件
此方法属于非静态处理器只能采用非静态注册方式
   
CLASS-METHODS h1 FOR EVENT e1 OF c1 IMPORTING p1 sender.
   
"
非静态方法处理非静态事件此方法属于非静态处理器只能采用非静态注册方式
   
METHODS: h2 FOR EVENT e2 OF
c1 IMPORTING sender,
              
"
非静态方法当然更可以处理静态事件此方法属于静态处理器只能采用静态注册方式
             h3
FOR EVENT ce1 OF c1 IMPORTING p2.
ENDCLASS.

CLASS c2 IMPLEMENTATION.
 
METHOD h1 .
   
WRITE: 'c2=>h1'.
 
ENDMETHOD.
 
METHOD: h2.
   
WRITE: 'c2->h2'.
 
ENDMETHOD.
 
METHOD: h3.
   
WRITE: 'c2->h3'.
 
ENDMETHOD.
ENDCLASS.

DATA: trigger TYPE REF TO c1,
      trigger2
TYPE REF TO c1,
     
handler TYPE REF TO c2.
START-OF-SELECTION.
 
CREATE OBJECT trigger.
 
CREATE OBJECT trigger2.
 
CREATE OBJECT handler.
  "
由于h1h2两个处理方法分别是用来处理非静态事件e1e2的,所以只能采用实例注册方式
 
SET HANDLER: c2=>h1 handler->h2 FOR trigger,
                
"h3
处理方法是用来处理静态事件ce1的,属于静态处理器,所以只能采用静态注册方式
                 handler
->h3.
  trigger
->trigger
( ).
  "
虽然trigger( )方法会触发 e1,e2,ce1 三种事件,但h1h2未向实例trigger2注册,而h3属于静态处理器,与实例无关,即好比向所有实例注册过了一样
  trigger2
->trigger( ).

image035

posted @ 2015-01-31 20:30  江正军  阅读(9212)  评论(0编辑  收藏  举报