Class是object的抽象描述,object只是在程序运行时才能存在。Object是由class描述的,并包含两个层次,inner layer和outer layer。Object的public component就是这个object的interface。Oo的主要目的就是为了保证object本身状态的consistency。Object的attributes一般是internal的,只能被它的method修改。对于具有相同attributes和methods的object他们也有自己的identity来区分。与OO概念相似的有function group,不同的是function group只能有一个instance,而object可以有任意个instance。
Interface是独立于class之外定义的。.它包含向attributes和methods这样的声明语句。其具体功能是通过class来实现的。这些class应该有统一的与外部联系的方式,并通过实现方法来实现interface的所有功能。在程序中你可以创建interface变量来指向interface,但是你不能instantiate一个interface。Interface变量用来指向不同class的object。
与customer exit不同的是,badi考虑到了软件修改的发布流程。Badi enhancement的实现至少需要一个interface以及相应的class来实现它,interface的实现由用户来完成。这种enhancement的一个优点是它提供了reuse的能力。一旦实现了,badi在软件的发布过程中仍然可以重新实现。Implementation本身也可以提供badi。
一个badi包含着enhancement components,其主要包含下面几种components:
l Program enhancements:program enhancements是通过interface methods来实现的,SAP程序来调取生成的badi class的interface methods。
l Menu enhancements:同customer exit一样,可以在badi中维护function code。这些menu entry在GUI definition中已经定义就可以在implemented badi看见。
l Screen enhancements:同customer exit一样你可以在badi中维护screen enhancements。
创建badi时,几个相关的部件就会被创建:interface和为实现interface而生成的class。生成的class主要实现下面的任务:过滤,如果你实施了一个过滤badi,那么这个class就会保证只有相关的implementation才会被调用。
Badi的执行流程:首先service class CL_EXITHANDLER会创建一个object reference,并产生调用program enhancement method的条件。当你定义BADI时,就会产生一个BADI class,用来implement badi interface。调用时,badi class的interface method就会被调用。Badi会搜索所有的BADI Implementation并调用implemented methods。
Badi在调用程序中的实现源代码如下:
REPORT <program_using_badi>.
DATA: r_var TYPE REF TO <badi-interface>.
START-OF-SELECTION.
CALL METHOD cl_exithandler=>get_instance
CHANGING
Instance = r_var.
CALL METHOD r_var->method
EXPORTING
<i_variables>
IMPORTING
<e_variables>.
END-OF-SELECTION.
首先你必须定义一个指向badi interface的reference variable。这个reference variable的名字不一定要包括badi的名字。第一次调用时一个object reference就会被创建,只用interface的method才会被这个reference object调用。可以通过这个reference object来调用你需要的enhancement中的方法。
可以通过t-code SE19来implement badi。
可以给implement class分配任何的名字,不过最好遵循以下规则:namespace以Y或Z开始,对于class的name以CL开始,implementation的name以IM开始,要implement method只要双击method name即可,系统会自动启动Class Builder editor。一旦完成代码编写,一定要激活它。
如果badi被激活,当调用程序执行时,相应的implementation methods也会被执行。一旦diactivate这个implementation,相应的方法就不会被调用。然而应用程序中的相关调用仍然会被执行。不同的是adapter class的instance不会找到激活的implementations。并不像CALL CUSTOMER-FUNCTION,CALL METHOD CL_EXITHANDLER=>GET_INSTANCE即使没用implementations,仍然会被调用。只有在original system中才可以activate或deactivate implementations,而subsequent systems则只能transport。如果badi只能有一个implementation,那么系统中仍然可以存在这个badi的多个implementation,只不过只能有一个激活版本。
同customer exit一样badi中也有menu enhancements。但是必须满足以下两个条件:1,必须预留了menu enhancement。2,必须在Badi的implementation中实现。Menu enhancements的function codes必须以+开始。如果相应的enhancement的badi implementation被激活,那么menu就会显示出来。你只能为single use badi创建function code,而且badi不能是filter dependent。这样就保证了一个或多个的badi不出现矛盾。如果用户在程序中选择了相应的以+开始的function code,那么系统就会调用相应的method。Method call和Menu enhancement是不可分离的,它们只能属于同一个badi。
通过badi builder SE18来创建badi。Badi有两个重要的属性,Reusable和filter-dependent。如果想让你的badi支持多个激活的implementation那么就要选择reusable。不过implementations的执行顺序不能被定义。即使badi本身不支持mulitiple use也可以同时存在多个implementations,只不过只能有一个激活的implementation。Badi如果filter dependent的,这样就可以设置调用的条件。Filter type必须是data element或者ABAP dictionary structure。Data element使用的domain的value table包含了implementation所需要的valid values。如果filter type使用的是structure,那么这适用于structure的每个字段。当调用enhancement method时,filter value必须传给interface。Badi中可以包含function code,需要输入program name,function code以及short description。局限性是不能够创建只包含function code的badi,menu enhancement既不能filter dependent也不能reusable。
系统提供了badi的interface和生成class的name。理论上可以将这些name改成任何你喜欢的name,但是保留系统推荐的name会使badi更加容易理解。生成的class的name遵循以下规则:namespace prefix + CL_ + EX_(代表 exit) + badi name。双击interface name就会进入class builder,就可以定义interface method。一个badi indterface可以有多个interface method。Class bulder的所有功能都可以使用,如定义interface method,定义method的interface parameters以及声明interface的attributes等。如果badi是filter dependent的,必须给他的每个method定义一个import parameter flt_val。一旦完成了interface的定义就要激活它。一旦修改了interface,badi class也会重新生成。也可以在badi维护事务中通过utilities->Regenerate来重新生成adapter class。Badi在程序中的调用过程:首先声明一个badi interface的reference variable。调用service class CL_EXITHANDLER的static method GET_INSTANCE。这个method返回required object的instance。这里属于narrow cast,所以通过这个variable只能调用interface methods。然后你就可以调用badi的方法了。示例如下:
DATA: r_var TYPE REF TO <badi-interface>.
START-OF-SELECTION.
CALL METHOD
Cl_exithandler=>get_instance
CHANGING
Instance = r_var.
CALL METHOD r_var-><method>
EXPORTING
<i_variables>
IMPORTING
<e_variables>/
如果使用filter dependent badi,要给参数flt_val传递一个适当的值。
对于ABAP virtual machine,screens和class是不能绑定到一块的。所以只用classical programs(type I,For M)才能作为screen的容器。Badi的screen enhancement也必须考虑到这点。当创建badi screen enhancement时,在应用程序的screen上要保留一块subscreen area。然后implementing program就会填充它。应用程序和subscreen的container program并不直接交换信息,而是通过生成的badi class。如果badi包含screen enhancements那么它就不能是reusable的。在subscreen tab你需要输入calling program,screen number和subscreen area。Implementing program和subscreen number是在implementation过程中指定的。
如果想通过badi实现screen enhancement,在应用程序中要实现以下步骤:
l 生成badi class
l 将badi class instance存入到refernce variable中
l 将数据传递给badi class
l 得到enhancement screen的program name和screen number
l 调用screen
在main screen的PAI,需要调用另外一个method把修改后的数据传回给application program。
实现screen enhancement的几个步骤:
l 首先通过adapter class CL_EXITHANDLER的factory method get_instance来得到生成的badi class的一个instance。并将其存储到一个reference variable中。DATA:EXIT TYPE REF TO <badi-interface>. CALL METHOD cl_exithandler=>get_instance CHANGING instance = exit.
l 然后implementation必须能够access badi instance。也就是说必须把reference variable赋给handler class的一个attribute。然后这个reference variable就会赋给badi class。通过下面的语句来实现这个步骤:CALL MEHTOD cl_exithandler=>set_instance_for_subsdcreens
l 为了使implementation获得数据需要通过两个步骤来实现。首先将data传给badi class,这些数据存储在这个方法的implementation的global attributes中,强烈建议在这个步骤提供sample code。通过badi中定义的mehtod来传递数据。然后存储在badi global attributes中的data就会被自动传到implementation的global attributes中,当然,implementation必须是active状态。使用的语句如下:CALL METHOD exit->put_data EXPORTING <data>.
l 在执行CALL SUBSCREEN语句之前,必须得到subscreen的screen number和program name,这个通过方法cl_exithandler=>get_prog_and_dynp_for_subsc来实现。如果没有active implementation,就会得到dummy function group(SAPLSEXM)的dummy subscreen (screen number 200)。如果存在active implementation,在implementation中指定的subscreen就会被使用。语句如下:CALL METHOD cl_exithandler=>get_prog_and_dynp_for_subscr EXPORTING … IMPORTING called_program = … called_dynpro = ..
l 调用相应的subscreen,如果没有active implementation,就会显示default empty subscreen。
l 如果在离开screen之后向得到Implementation中的data,则需要使用method:CALL METHOD exit->get_data IMPORTING <data>。
Implement badi screen enhancement的步骤如下:
l 创建badi的implementation指定包含subscreen的程序名和screen number
l 创建指定的program
l Layout指定的subscreen
l Implementing program必须得到badi的instance
l 从应用程序传递给badi的数据可以被取得。
l 如果想将修改后的数据返回给application program,需要调用相应的方法。
得到badi class instance的方法是CALL METHOD cl_exithandler=>get_instance_for_subscreens,这个reference是通过方法cl_exithandler=>set_instance_for_subscreen来传递的。这允许你在implementation中访问badi的attributes以及interface methods。Implementing program通过方法:exit->get_data IMPORTING <data>来获取badi中的data。通过方法exit1->put_data EXPORTING <data>将修改后的data传回给badi class的instance。
Filter type扩展性局限于以下几个方面:
l Filter type参考的domain必须符合下面的几个条件:
Ø Domain要指向cross client value table。这个value table只有一个使用的data element的domain是这个domain的key field。
Ø Domain有一个两个key field的text table,一个key field使用的是这个domain本身,另一个key field是language field。其必须还得有一个text field,这个text field的类型为TEXT或TXT。在ABAP DICTIONARY中必须给text field指定一个value table。
Ø 这两个table的delivery class必须是E或S
如果没有active implementations,那么由enhancement provider提供的default implementation就会被执行。在badi definition中通过goto->default code就可以创建default implementation。还可以创建一个sample implementation。通过goto->sample code就可以创建。几种增强方法的比较:
| Customer Exit | BTE | BADI |
Source code | + | + | + |
Menus | + | - | + |
Screens | + | - | + |
Table | + | - | [+] |
Administration levels | + | - | + |
reusable | - | + | + |
Filter specific | - | + | + |
BADI DEFINITION中的name conventions
l Badi definition: <badi> or z<badi> or /../<badi>
l Interface:IF_EX_<badi> or ZIF_EX_<badi> or /../IF_EX_<badi>
l Methods:any name
l Generated badi class(adapter class) cl_ex_<badi> or zcl_ex_<badi> or /../cl_ex_<badi>
BADI IMPLEMENTATION中的name conventions
l BADI implementation <impl> or z<impl> or /../<impl>
l Interface: IF_EX_<badi> or ZIF_EX_<badi> or /../IF_EX_<badi>
l Methods:在badi definition中定义
l Implementing class:CL_IM_<impl> ZCL_IM_<impl> /../CL_IM_<impl>
找到badi的方法:
l 在应用程序中搜索CL_EXITHANDLER
l REPOSITORY INFORMATION SYSTEM
l 相关component的IMG
这哥们写的挺有建树,但是还是看不懂,不知道为嘛!
感觉到好自卑啊!太深了!