*&---------------------------------------------------------------------*
*& Program Name :ZLPJ_OO
*& Title : 面向对象
*& Module Name : OO
*& Author :PPJLI
*& Create Date :12.07.2019 20:52:07
*& Program Type :Report Program
*& Requested by :开发项编号
*& Description :面向对象的,创建本地类
*&------------------- -------------------------------------------------*
REPORT YTST_PPJLI_OO.
*--------------------------------------------------------------------*
*实例组件:声明方式(属性:data; 方法:method; 访问:object->comp)
*静态组件:声明方式(属性:class-data;方法:class-method;访问:class=>comp)
*两个组件之间的区别:实例组件依附于实例,不同的实例之间相互独立;静态组件存在于类中
*--------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& 接口的定义
*&---------------------------------------------------------------------*
INTERFACE INTER.
METHODS WRITE_INTER.
ENDINTERFACE.
* DEFINITION:定义类中的项目(属性,方法,事件; 公有、私有、保护、友好)
CLASS LCL_COMPT DEFINITION.
* &---------------------------------------------------------------------*
* & *指明类中项目的访问区域,知道遇到下一个访问区域,该访问区域停止
* &---------------------------------------------------------------------*
PUBLIC SECTION.
TYPES: CTY_CHAR20 TYPE C LENGTH 20.
TYPES: CTY_CHAR5 TYPE C LENGTH 5.
TYPES: GTY_P02 TYPE P LENGTH 10 DECIMALS 2.
"实例属性
DATA GV_CHAR TYPE C LENGTH 20 VALUE '实例属性'.
DATA:GV_CONCATENATE TYPE CTY_CHAR20.
* 定义一个工作区 参照类型为学校数据库表
DATA: GS_SCHOOL TYPE ZSCHOOL_LPJ_01.
CONSTANTS C_DATA TYPE C LENGTH 20 VALUE '常量'.
"实例方法
METHODS WRITE_CHAR.
METHODS WRITE_INSTANGE.
METHODS SET_VALUE IMPORTING I_VALUE TYPE CTY_CHAR20. "用于外部参数的调用; 对GV_CHANGE进行赋值 引入参数P_VALUE
METHODS GET_VALUE EXPORTING E_VALUE TYPE CTY_CHAR20. "获取GV_CHANGE的值
METHODS CON_VALUE IMPORTING I_VALUE1 TYPE CTY_CHAR5 OPTIONAL "OPTIONAL可选参数
I_VALUE2 TYPE CTY_CHAR5
I_VALUE3 TYPE CTY_CHAR5
EXPORTING E_SUBRC TYPE C
E_CONCAT TYPE CTY_CHAR20. "多个参数
METHODS GET_DATA IMPORTING P_SCHOOL LIKE GS_SCHOOL-ZSCHOOL.
*&---------------------------------------------------------------------*
*& 返回参数
*& 1. returning不能和changing和exporting同时使用;
*& 2. 只能接收一个返回参数
*&---------------------------------------------------------------------*
METHODS RET_VALUE IMPORTING I_VALUE1 TYPE CTY_CHAR5 OPTIONAL "OPTIONAL可选参数
I_VALUE2 TYPE CTY_CHAR5
I_VALUE3 TYPE CTY_CHAR5
RETURNING VALUE(E_CONCAT) TYPE CTY_CHAR20. "返回参数
METHODS GET_ROUND_01 IMPORTING VALUE(I_R) TYPE GTY_P02
EXPORTING VALUE(E_ROUND) TYPE GTY_P02
EXCEPTIONS NO_ZERO. "异常
METHODS GET_ROUND_02 IMPORTING VALUE(I_R) TYPE GTY_P02
VALUE(I_PI) TYPE GTY_P02 "将圆周率也作为参数传入
RETURNING VALUE(E_ROUND) TYPE GTY_P02.
METHODS ADD_DATA.
" 静态方法
CLASS-METHODS WRITE_STATIC.
" 静态属性
CLASS-DATA GV_STATIC TYPE C LENGTH 20 VALUE '静态属性'.
" 构造器方法
METHODS CONSTRUCTOR IMPORTING I_CHAR TYPE CTY_CHAR20.
* 接口的引用
INTERFACES INTER.
* 接口别名的声明
ALIASES WRITE_INTERFACE FOR INTER~WRITE_INTER.
* 事件
EVENTS DATA_EXIST EXPORTING VALUE(PS_SCHOOL) LIKE GS_SCHOOL. "因为GS_SCHOOL是一个对象不是类型,所以用like
EVENTS MOD_10 EXPORTING VALUE(P_INT) TYPE I.
PROTECTED SECTION.
" 声明静态属性
CLASS-DATA GV_SUBER TYPE C LENGTH 20 VALUE 'SUPER CLASS'.
CONSTANTS C_PI TYPE GTY_P02 VALUE '3.14'.
PRIVATE SECTION.
"静态属性
CLASS-DATA GV_STATIC_PRI TYPE C LENGTH 20 VALUE '私有静态属性'.
CLASS-DATA GV_CHANGE TYPE CTY_CHAR20.
DATA: GV_INT TYPE I.
ENDCLASS.
* IMPLEMENTATION:定义类中的方法的内容
CLASS LCL_COMPT IMPLEMENTATION.
METHOD WRITE_CHAR.
WRITE:/ '实例方法:',GV_CHAR.
" WRITE:/ GV_STATIC. 实例方法可以访问静态属性
ENDMETHOD.
METHOD WRITE_STATIC.
WRITE:/ '静态方法:', GV_STATIC.
* WRITE:/ '访问实例方法',GV_CHAR. "在静态方法中不可以访问实例组件
ENDMETHOD.
METHOD WRITE_INSTANGE. "实例
WRITE:/ '实例方法',GV_STATIC.
ENDMETHOD.
METHOD SET_VALUE.
GV_CHANGE = I_VALUE.
ENDMETHOD.
METHOD GET_VALUE.
E_VALUE = GV_CHANGE.
ENDMETHOD.
METHOD CON_VALUE.
CONCATENATE I_VALUE1 I_VALUE2 I_VALUE3 INTO GV_CONCATENATE. "CONCATENATE:连接
IF SY-SUBRC = 0.
E_SUBRC = 'S'.
E_CONCAT = GV_CONCATENATE.
ELSE.
E_SUBRC = 'E'.
ENDIF.
ENDMETHOD.
METHOD RET_VALUE.
CONCATENATE I_VALUE1 I_VALUE2 I_VALUE3 INTO GV_CONCATENATE. "CONCATENATE:连接
IF SY-SUBRC = 0.
E_CONCAT = GV_CONCATENATE.
ENDIF.
ENDMETHOD.
METHOD GET_ROUND_01.
*针对异常加入的判断
IF I_R < 0.
RAISE NO_ZERO.
ENDIF.
E_ROUND = C_PI * I_R ** 2.
ENDMETHOD.
*将圆周率作为常量
* METHOD GET_ROUND_02.
* E_ROUND = C_PI * I_R ** 2.
* ENDMETHOD.
*将圆周率作为参数传入
METHOD GET_ROUND_02.
E_ROUND = I_PI * I_R ** 2. "计算面积
ENDMETHOD.
METHOD CONSTRUCTOR.
WRITE:/ '执行了构造器函数'. "执行结果返回两个语句,是因为声明了两个OBJECT 对象
WRITE:/ I_CHAR.
ENDMETHOD.
METHOD WRITE_INTERFACE.
WRITE:/ '接口中的方法'.
ENDMETHOD.
METHOD GET_DATA.
SELECT SINGLE *
FROM ZSCHOOL_LPJ_01
INTO CORRESPONDING FIELDS OF GS_SCHOOL
WHERE ZSCHOOL = P_SCHOOL.
IF SY-SUBRC = 0.
RAISE EVENT DATA_EXIST
EXPORTING
PS_SCHOOL = GS_SCHOOL. "同方向的
ELSE.
WRITE:/ '取数失败!'.
ENDIF.
ENDMETHOD.
METHOD ADD_DATA.
DATA: LV_MOD TYPE I.
GV_INT = GV_INT + 1.
LV_MOD = GV_INT MOD 10.
IF LV_MOD = 0.
RAISE EVENT MOD_10 EXPORTING P_INT = GV_INT.
ENDIF.
ENDMETHOD.
ENDCLASS.
*&---------------------------------------------------------------------*
*& 继承LCL_COMPT INHERITING:继承
*&---------------------------------------------------------------------*
CLASS LCL_SUB DEFINITION INHERITING FROM LCL_COMPT.
PUBLIC SECTION.
"声明一个方法
METHODS WRITE_SUPER.
METHODS GET_ROUND_02 REDEFINITION. "针对父类中存在的方法;对父类方法GET_ROUND_02进行重定义
METHODS CALCULATE_CIRCLE IMPORTING I_R TYPE GTY_P02.
ENDCLASS.
CLASS LCL_SUB IMPLEMENTATION.
"使用声明的方法
METHOD WRITE_SUPER.
WRITE:/ 'PUBLIC SECTION.',GV_CHAR. "共有部分
WRITE:/ 'PROTECT SECTION',GV_SUBER. "保护部分
"WRITE:/ 'PRIVATE SECTION',GV_STATIC_PRI. "私有部分 不能被继承类访问,只能内部访问
ENDMETHOD.
METHOD GET_ROUND_02.
" 父类中 GET_ROUND_02 计算面积
DATA: LV_CIRCLE TYPE P LENGTH 2.
CALL METHOD SUPER->GET_ROUND_02
EXPORTING
I_R = I_R
I_PI = '3.14'
RECEIVING
E_ROUND = LV_CIRCLE.
WRITE:/ LV_CIRCLE.
E_ROUND = 2 * C_PI * I_R.
LV_CIRCLE = E_ROUND.
WRITE:/ '周长:',LV_CIRCLE.
ENDMETHOD.
METHOD CALCULATE_CIRCLE.
DATA: LV_SPACE TYPE P LENGTH 2.
CALL METHOD GET_ROUND_02
EXPORTING
I_R = I_R
I_PI = '3.14'
RECEIVING
E_ROUND = LV_SPACE.
WRITE:/ LV_SPACE.
* 子类中GET_ROUND_02计算周长
CALL METHOD ME->GET_ROUND_02 "ME指定当前类(子类)中的方法
EXPORTING
I_R = I_R
I_PI = '3.14'
RECEIVING
E_ROUND = LV_SPACE.
WRITE:/ LV_SPACE.
ENDMETHOD.
ENDCLASS.
*&---------------------------------------------------------------------*
*& 定义一个抽象类
*&---------------------------------------------------------------------*
CLASS LCL_ABSTRACT DEFINITION ABSTRACT.
PUBLIC SECTION.
* METHODS WRITE_ABSTRACT. " 在抽象类中可以定义实例方法 , 如果没有实例方法,可以不需要实现;在非抽象类中不可以定义抽象方法
METHODS WRITE_ABSTRACT_02 ABSTRACT. "抽象类不需要实现
ENDCLASS.
*CLASS LCL_ABSTRACT IMPLEMENTATION.
* METHOD WRITE_ABSTRACT.
* WRITE:/ '抽象类中的实例方法'.
* ENDMETHOD.
*ENDCLASS.
CLASS LCL_SUB_02 DEFINITION INHERITING FROM LCL_ABSTRACT. "继承抽象类
PUBLIC SECTION.
METHODS WRITE_ABSTRACT_02 REDEFINITION. "重定义抽象类中的抽象方法
ENDCLASS.
*&---------------------------------------------------------------------*
*& 抽象类中的抽象方法,必须通过继承类实现
*&---------------------------------------------------------------------*
CLASS LCL_SUB_02 IMPLEMENTATION.
METHOD WRITE_ABSTRACT_02. "实现重定义的抽象方法
WRITE:/ '抽象类中的抽象方法'.
ENDMETHOD.
ENDCLASS.
*&---------------------------------------------------------------------*
*& 事件接收器
*&---------------------------------------------------------------------*
CLASS LCL_HEANDLER DEFINITION.
PUBLIC SECTION.
METHODS WRITE_DATA FOR EVENT DATA_EXIST OF LCL_COMPT
IMPORTING PS_SCHOOL.
METHODS WRITE_INT FOR EVENT MOD_10 OF LCL_COMPT
IMPORTING P_INT.
ENDCLASS.
CLASS LCL_HEANDLER IMPLEMENTATION.
METHOD WRITE_DATA.
WRITE:/ PS_SCHOOL-ZSCHOOL,PS_SCHOOL-ZADDRESS.
ENDMETHOD.
METHOD WRITE_INT.
WRITE:/ P_INT.
ENDMETHOD.
ENDCLASS.
* 声明一个对象
DATA LCL_OBJECT TYPE REF TO LCL_COMPT. "参照LCL_COMPT类声明具体的OBJECT对象。
DATA LCL_OBJECT_2 TYPE REF TO LCL_COMPT. "参照LCL_COMPT类声明具体的OBJECT对象。
START-OF-SELECTION.
* 创建对象的过程就是实例化;创建的对象就是实例
CREATE OBJECT LCL_OBJECT
EXPORTING
I_CHAR = '实例1'. "实例化
CREATE OBJECT LCL_OBJECT_2
EXPORTING
I_CHAR = '实例2'. "实例化
* 实例属性,在在不同的实例之间独立
WRITE:/ '访问实例属性:',LCL_OBJECT->GV_CHAR. "访问实例属性 实例方法和实例属性通过实例来调用
LCL_OBJECT->GV_CHAR = '更换char的值'. "修改实例1
CALL METHOD LCL_OBJECT->WRITE_CHAR. "实例1的值
CALL METHOD LCL_OBJECT_2->WRITE_CHAR. "实例2的值
* 静态属性,不依附于实例
WRITE:/ '访问静态属性:',LCL_COMPT=>GV_STATIC. "访问静态属性
LCL_COMPT=>GV_STATIC = '更换静态属性的值'.
CALL METHOD LCL_COMPT=>WRITE_STATIC. "静态方法
*&---------------------------------------------------------------------*
*& 带有参数的方法的调用 SET_VALUE和GET_VALUE是实例方法,通过实例调用
*&---------------------------------------------------------------------*
DATA: GV_DATA TYPE LCL_OBJECT->CTY_CHAR20.
CALL METHOD LCL_OBJECT->SET_VALUE
EXPORTING
I_VALUE = '赋值CHAR变量'.
CALL METHOD LCL_OBJECT->GET_VALUE
IMPORTING
E_VALUE = GV_DATA .
WRITE:/ GV_DATA.
* method中的参数(区分exporting和returning的区别)
DATA: GV_SUBRC TYPE C.
CALL METHOD LCL_OBJECT->CON_VALUE
EXPORTING
* I_VALUE1 = 'BJ;'
I_VALUE2 = 'CHIA;'
I_VALUE3 = 'GREAT'
IMPORTING
E_CONCAT = GV_DATA
E_SUBRC = GV_SUBRC.
WRITE:/ GV_DATA ,GV_SUBRC.
CALL METHOD LCL_OBJECT->RET_VALUE
EXPORTING
I_VALUE1 = 'BJ;'
I_VALUE2 = 'CHIA;'
I_VALUE3 = 'GREAT'
RECEIVING
E_CONCAT = GV_DATA.
WRITE:/ GV_DATA.
*访问常量
WRITE:/ LCL_COMPT=>C_DATA. "通过类访问 常量一般用类访问
WRITE:/ LCL_OBJECT->C_DATA. "通过实例访问
PARAMETERS: P_R TYPE P LENGTH 10 DECIMALS 2.
DATA: GV_ROUND TYPE P LENGTH 10 DECIMALS 2.
CONSTANTS: C_PI TYPE P LENGTH 10 DECIMALS 2 VALUE '3.14'.
CALL METHOD LCL_OBJECT->GET_ROUND_01
EXPORTING
I_R = P_R
IMPORTING
E_ROUND = GV_ROUND
*针对异常加入的语句
EXCEPTIONS
NO_ZERO = 1.
IF SY-SUBRC = 1.
WRITE:/ '半径不能小于0'.
ENDIF.
*CALL METHOD LCL_OBJECT->GET_ROUND_02
* EXPORTING
* I_R = P_R
* RECEIVING
* E_ROUND = GV_ROUND.
*或者下面的方法 圆周率作为常量
*GV_ROUND = LCL_OBJECT->GET_ROUND_02( P_R ). "注意括号和参数之间的空格
*圆周率作为参数传入
GV_ROUND = LCL_OBJECT->GET_ROUND_02( I_R = P_R
I_PI = C_PI ).
WRITE:/ '圆面积为:',GV_ROUND.
DATA: OBJECT_SUB TYPE REF TO LCL_SUB. "根据子类声明一个对象
CREATE OBJECT OBJECT_SUB
EXPORTING
I_CHAR = '子类实例化'. "因为子类继承了父类,并且父类中有构造方法且指明传输参数,所以在这块的声明处 要对CONSTRUCTOR的参数 I_CHAR 进行传输。
CALL METHOD OBJECT_SUB->GET_ROUND_02
EXPORTING
I_R = P_R
I_PI = '3.14'
RECEIVING
E_ROUND = GV_ROUND.
* 接口中方法调用
CALL METHOD LCL_OBJECT->WRITE_INTERFACE.
* 事件的注册及调用
DATA: EVENT_HANDLER TYPE REF TO LCL_HEANDLER. "声明一个对象
DATA: EVENT_HANDLER_2 TYPE REF TO LCL_HEANDLER.
CREATE OBJECT EVENT_HANDLER. "实例化
CREATE OBJECT EVENT_HANDLER_2.
* 注册 :SET HANDLER 实例2—>方法 for 实例1
SET HANDLER EVENT_HANDLER->WRITE_DATA FOR LCL_OBJECT.
SET HANDLER EVENT_HANDLER->WRITE_DATA FOR LCL_OBJECT_2.
SET HANDLER EVENT_HANDLER_2->WRITE_DATA FOR LCL_OBJECT.
SET HANDLER EVENT_HANDLER->WRITE_DATA FOR OBJECT_SUB.
SET HANDLER EVENT_HANDLER->WRITE_INT FOR LCL_OBJECT.
*&---------------------------------------------------------------------*
*& 此处打断点,查看事件的过程
*&---------------------------------------------------------------------*
CALL METHOD LCL_OBJECT->GET_DATA
EXPORTING
P_SCHOOL = '欧亚学院'.
CALL METHOD LCL_OBJECT_2->GET_DATA
EXPORTING
P_SCHOOL = '欧亚学院'.
WRITE:/ '调用子类中的方法:'.
CALL METHOD OBJECT_SUB->GET_DATA
EXPORTING
P_SCHOOL = '欧亚学院'.
DO 50 TIMES.
CALL METHOD LCL_OBJECT->ADD_DATA.
ENDDO.
*&--------------------------------------------------------------------*
*&--------------------------------------------------------------------*
*& 例子:
*& 需求:
*& 设置一个数字从1 循环到50,当他是10的倍数的时候,触发事件,输出当前的值
*&---------------------------------------------------------------------*