ABAP 面向对象编程-1

本文详细解析了ABAP面向对象编程中的关键概念,如继承、多态和事件,以及类的定义(局部类、全局类、属性和方法),并介绍了如何使用接口和对象实例化。重点讲解了类的实例化、静态属性、构造器和方法调用的细节。
摘要由CSDN通过智能技术生成

8. ABAP 面向对象编程

8.1 与面向过程编程的区别

待总结,刚看完面向过程ABAP,个人感觉像C语言中的主函数调用子函数。
面向对象呢,就是封装啊,继承啊,一些比较复杂的概念。
回头补。

8.2 回顾ABAP变量和数据类型

数据类型:就是一个变量装啥样的数据。
变量:声明了一个变量,它就会指向内存一块地方来保留数据的值。就是说我要一块地方。
在变量声明过程中指定的数据类型,操作系统会分配内存,决定怎么在内存中来保存这个数据。
插播: 字和字节的区别
bit: binary digit(二进制数)的简写,要么是1,要么是0,是指最小的数据单位。就是个有电没电的电路信号。
byte:一字节等于8bit。为啥?一开始美国人搞的ASCII码,127位就囊括了所有数字,字母和特殊字符。对于美国人来讲,这个ASCII码的127位就用8个bit就够了。所以byte作为内存或者外部存储的最小单位。(后来有扩展)
在这里插入图片描述

1MB = 8Mb
bit 一般用来衡量速度:Mbps
这个意思是,一秒内把多少位字从一个设备给移到另一个设备。宽带10Mbps就是这个意思。一秒就有这么多bit到你手机上。为啥用bit来衡量速度,不用byte? 你发送出去的数据,比如邮件一般都是被分解成数据包,然后从不同方向发送,最后到达别人的接收处是顺序混乱需要重排的。所以呢,这种不稳定的数据流不好划分字节,那就用比特衡量。

byte 用来衡量大小:MB
相对于内存来说,1 byte是最小存储单元。硬盘,U盘和系统内存一般用这个单位。软件大小也按这个来衡量。
那么比如HI这个单词,就需要两个字节。Hello就需要5个字节。

插播结束

现在回到ABAP的数据类型。
在这里插入图片描述
基本数据类型就有以下这么多。有些是定长的,有些是不定长的。
在这里插入图片描述
在这里插入图片描述
比如说定义一个I整型的,那系统就会指定4个字节空间给你,那么你的这个数字最大就是± 2的31次方。
对于一个字符的,我觉得也是1byte。只不过对于字符型的,直接用字符作为大小。65535个byte。

还有些可以参照这里:别人写的.

接下篇: 在ABAP对象中使用内表.

以下内容在下篇:ABAP 面向对象编程-2.

8.3 面向对象中的概念
8.3.1 继承

就是说类和别人分享自己的结构和方法

8.3.2 多态

共用一个沟通接口的不同对象

8.3.3 事件

用来对对象作出反应及触发事件

8.4 类

类要定义后实现。
类似于C语言要定义类的对象和方法。同时对象也有公有私有。
在ABAP中定义类,对象就是attribute,还有types,interface可以定义。等等。

8.4.1 类的定义

类分为全局类和局部类。
全局类和接口在 SE24构建。最终存储在SAP Class Reposistory的class Pools里面。所有的ABAP程序都可以访问全局类。
局部类就是本地类,在ABAP程序内部自己定义,也就是说SE38弄。
那么其实大家最好用全局类。默认用Y或Z开头的。局部类么,你就随便用啥开头。

8.4.1.1 局部类

就是纯的搞代码。定义和实现。
定义就是名称,属性,方法。
实现就是方法的代码。

CLASS user DEFINITION.
  PUBLIC SECTION.
  DATA: name   TYPE c LENGTH 30,
        age    TYPE i,
        gender TYPE c LENGTH 1 READ-ONLY.
  CLASS-DATA : count TYPE i.
  PRIVATE SECTION.
  DATA : loginid TYPE c LENGTH 20,
         pwd     TYPE c LENGTH 15.
  ENDCLASS.

类的定义中还有方法:
作为一个BW工作者,经常在转换里面看到:

  methods GLOBAL_END
    importing
      !REQUEST type RSREQUEST
      !DATAPACKID type RSDATAPID
      !SEGID type RSBK_SEGID
    exporting
      !MONITOR type RSTR_TY_T_MONITORS
    changing
      !RESULT_PACKAGE type _ty_t_TG_1
    raising
      CX_RSROUT_ABORT
      CX_RSBK_ERRORCOUNT .
  methods NEW_RECORD__END_ROUTINE
    importing
      !SOURCE_SEGID type RSTRAN_SEGID default 0001
      !SOURCE_RECORD type SYTABIX
    exporting
      !RECORD_NEW type SYTABIX .

在类的方法定义中。
Import: 就是传给这个方法的值。
export:就是从方法中传出去的值。
changing:就是两者皆有,传入到方法的值,最后更改后再传出。
raising:啥例外。

注意,方法的定义也是在类中的,实际上endclass应该在方法定义结束之后。

8.4.1.2 属性

就是类中的数据字段,对象。在类声明的时候声明。在不同的位置,比如public section,private section。私有的就是说,只有我类里面的组件能访问,比如类里面的方法。类之外的不行。
属性分为对象实例和静态属性。
对象实例用DATA声明。上面的例子里有。
(20220411这个现在来看又有些不理解了,对象作为一种特殊的变量,也是要先声明一下的,就是data 对象名 type ref to 类名。这个其实是声明一个对象类型,然后当然还要实例化对象,就是create object 对象名,实例化了之后,你去看代码其实是给这个实例化的对象分配了一个和类一样的,有类的所有属性和方法的空间了。type ref to我理解就是指针指向类,这具体以后再理解)
静态属性用CLASS-DATA声明。如果静态属性改了,大家都能看到。所以这个家伙在public区。

8.4.1.3 方法

类中的对象的行为。方法可以访问类的属性。就是说它定义的对象空间。方法里面可以包含参数。当你去call这个method的时候,就传入数值给这个方法。方法的声明在类的声明里,实现在类的实现里。METHOD…ENDMETHOD。
如果是静态方法也是一样的用CLASS-METHOD。
不同的就是静态方法调用的时候是用以下语法。
实际上类里定义的属性,方法等等,如果光定义,那它是不会有啥执行的,那咋办,所以要创建对象将对象实例化了之后,再去调用类的方法。这时也就是说我对象是实例化了的,我可以有空间去执行方法的。也可以填值进入那些属性的。

call method classname=>methodname

实例方法的调用如下:如果只import一个参数,那就把参数放在圆括号里,括号前没有空格,括号后有空格。

classname->methodname( data )

如果方法里不止import一个参数,那就用形参=实参成对的把实参赋值给形参。

classname->methodname( param1 = data1 param2 = data2 ).

如果不是只import参数进去,那就把参数的类型也带上:
注意这里export和import是反着来的。
因为你是call别人的方法。就是说我在这里call一个方法去干活。就是我叫一个小弟去干活。那我要export一个指令给他去。到他那边呢,他就接了也就是import了这个指令。等他除了完了export出来然后我再接进来,就是import进来。
如果你call的那个method是returning, 我们这边call的就是receiving。

calssname->methodname( EXPORTING param1 = data1 param2 = data2
                       IMPORTING param3 = data3 param4 = data4
                       CHANGING param5 = data5 param6 = data6).

懂了这些我觉得我一个搞BW的差不多能看懂代码了。
说实话我看到这里我觉得对我来说又是知识盲区了。我觉得我得去把C语言捡起来了。

REPORT ztest.

CLASS user DEFINITION.
  PUBLIC SECTION.
  DATA: name   TYPE c LENGTH 30,
        age    TYPE i,
        gender TYPE c LENGTH 1 READ-ONLY,
        status TYPE c LENGTH 1.
  CLASS-DATA : count TYPE i.

  METHODS setname
    IMPORTING namein TYPE c.

  METHODS getname
    EXPORTING nameout TYPE c.

  METHODS setstatus
    CHANGING newstatus TYPE c.

  METHODS getstatustext
    IMPORTING VALUE(statcode) TYPE c
    RETURNING VALUE(stattext) TYPE string.



  PRIVATE SECTION.
  DATA : loginid TYPE c LENGTH 20,
         pwd     TYPE c LENGTH 15.
  ENDCLASS.

  CLASS user IMPLEMENTATION.
    METHOD setname.
      name = namein.
    ENDMETHOD.

    METHOD getname.
      nameout = name.
     ENDMETHOD.

    METHOD setstatus.
      IF newstatus CO 'MF'.
         status = newstatus.
      newstatus = '1'.
      ELSE.
        newstatus = '2'.
      ENDIF.
    ENDMETHOD.

    METHOD getstatustext.
      CASE statcode.
        WHEN '1'.
          stattext = 'Male'.
        WHEN '2'.
          stattext = 'Female'.
        WHEN OTHERS.
          stattext = 'Unknown'.
      ENDCASE.
    ENDMETHOD.

    ENDCLASS.
CLASS car DEFINITION.

  PUBLIC SECTION.
  CLASS-DATA  carnum  TYPE i.

  METHODS setnumseats
    IMPORTING numseat TYPE i.

  METHODS gofaster
    IMPORTING increment TYPE i
    EXPORTING result TYPE i.


  METHODS goslower
    IMPORTING decrement TYPE i
    RETURNING VALUE(result) TYPE i.

  PRIVATE SECTION.
  DATA: make     TYPE c LENGTH 20,
        model    TYPE c LENGTH 20,
        seatsnum TYPE i,
        speed    TYPE i,
        maxsped  TYPE i.


ENDCLASS.

CLASS car IMPLEMENTATION.
   METHOD setnumseats.
     seatsnum = numseat.
   ENDMETHOD.

   METHOD gofaster.
     DATA temspeed type i.
     temspeed = speed + increment.
     IF temspeed <= maxsped.
       result = temspeed.
     ELSE.
       result = maxspeed.
     ENDIF.

   ENDMETHOD.

   METHOD goslower.
     DATA temspeed type i.
     temspeed = speed - decrement.
     IF speed >= 0.
       result = temspeed.
     ELSE.
       result = 0.
     ENDIF.

   ENDMETHOD.
ENDCLASS.
REPORT ztest.

CLASS car DEFINITION.

  PUBLIC SECTION.
  CLASS-DATA  carnum  TYPE i.

  METHODS constructor
   IMPORTING
        make     TYPE c
        model    TYPE c
        seatsnum TYPE i
        speed    TYPE i
        maxsped  TYPE i.

  METHODS viewcar.



  METHODS setnumseats
    IMPORTING numseat TYPE i.

  METHODS gofaster
    IMPORTING increment TYPE i
    EXPORTING result TYPE i.


  METHODS goslower
    IMPORTING decrement TYPE i
    RETURNING VALUE(result) TYPE i.

  PRIVATE SECTION.
  DATA: make     TYPE c LENGTH 20,
        model    TYPE c LENGTH 20,
        seatsnum TYPE i,
        speed    TYPE i,
        maxsped  TYPE i.


ENDCLASS.

CLASS car IMPLEMENTATION.

  METHOD constructor.
    me->make     = make. " make是constructor的参数, me->make是对象的属性
    me->model    = model.
    me->seatsnum = seatsnum.
    me->speed    = speed.
    me->maxsped  = maxsped.
    carnum   = carnum + 1.
  ENDMETHOD.


  METHOD viewcar.
    WRITE:/ make.
    WRITE:/ model.
  ENDMETHOD.

   METHOD setnumseats.
     seatsnum = numseat.
   ENDMETHOD.

   METHOD gofaster.
     IF speed >= maxsped.
       result = speed.
     ELSE.
       result = speed + increment.
     ENDIF.

   ENDMETHOD.

   METHOD goslower.
     IF speed >= 0.
       result = speed - decrement.
     ELSE.
       result = 0.
     ENDIF.

   ENDMETHOD.


ENDCLASS.

START-OF-SELECTION.
  DATA car1 TYPE REF TO car.
  CREATE OBJECT car1
     EXPORTING
       make = 'AUDI'
       model = 'A4'
       seatsnum = 5
       speed    = 60
       maxsped  =  120.
  uline.
report Zclass.
class Zclass DEFINITION.
  PUBLIC SECTION.
    DATA: 
      mv_value TYPE String.
    CLASS-DATA:
      gv_value TYPE String.
    METHODS:
      set_value IMPORTING iv_value TYPE String.
      display_value.
endclass.

Class zclass IMPLEMENTATION.
  Method display_value.
    Write:/ 'instance value:' mv_value.
    Write:/ 'static value:' gv_value.
  ENDMethod.
  Mehtod set_value.
    mv_value = iv_value.
  ENDMethod.
ENDClass.

Start-of-selection.
  DATA: lo_class TYPE REF TO zclass.
  Create object lo_class.

  Call Method lo_class->set_value
    Exporting 
       iv_value = ' Hello A'.
  zclass=>gv_value = 'Hello B'.
  Call Method lo_class->display_value.
 

constructor这方法,用于在object实例化之后,来初始化一些属性的。它只能在public区,只能有importing的参数。
那么这里有一点要理解的就是,我类里面是确实设定了很多属性的。当我去定义方法的时候,方法里面要去import导入一些参数,虽然这些参数就是得和属性一样的类型,但是不要用一样的名字。类中创建了实例化对象之后,对象就把类的所有属性和方法拿过来了。当我去调用方法的时候,如果我首先执行了constructor方法来初始化一些类的属性,也就是在constructor方法定义的时候,我import的都是类的属性一样的对象。如果我用了一样的名字,那么系统就不知道谁是类的属性,谁是方法的参数。就像下面这样。

  METHODS constructor
   IMPORTING
        make     TYPE c
        model    TYPE c
        seatsnum TYPE i
        speed    TYPE i
        maxsped  TYPE i.
        
class car IMPLEMENTATION.

method constructor. 
       make = make. 
       model = model. 
       seats = seats.
       maxspeed = maxspeed.
       numbers = numbers + 1.
ENDMETHOD.
       

而这个时候,就可以用到self-reference.
这个constructor是对于类的对象的构造方法。那么我要把import进来的参数赋值给对象。
所以加个me->就是告诉系统,左边的才是要赋值的对象的属性。
因为,当你执行这个constructor的方法的时候,它的import进去的参数,就会赋值给对象属性。

  METHOD constructor.
    me->make     = make. " make是constructor的参数, me->make是对象的属性
    me->model    = model.
    me->seatsnum = seatsnum.
    me->speed    = speed.
    me->maxsped  = maxsped.
    carnum   = carnum + 1.
  ENDMETHOD.
8.4.1.4 全局类

那就是SE24来搞了。
在这里插入图片描述
在这里你看到有特性,接口,友元,属性,方法,事件,类型。
特性页,类对象实例化生成。
在这里插入图片描述
public: 类可以在任意可见的地方进行初始化。
private:只能在类自身中创建类的实例。
protected:只能在类自身或者类的子类中创建类实例。
abstract:不可以创建实例。

一般选public。

属性
就是类的数据了。数据的具体值就是以后对象的值了。
在这里插入图片描述
那么一个个的第一个level:
就是属性的三个定义级别,分别是实例变量属性,静态属性和常量。
在这里插入图片描述
instance attribute既然是实例变量属性,就是说它这个类里的要经过创建成为对象实例之后才能使用它。对类的实例化的对象有效,每一个对象的实例化属性都有自己的唯一值。相当于局部类中用DATA声明的变量。
static attribute静态变量,相当于全局共享。类的所有对象都能用。但是任何一个对象对它的修改都将影响全局。
一般还是别用对象实例方法来改了,搞一个类的静态方法来访问修改。
可以通过对象访问,或者类名访问:

DATA: lo_class TYPE REF TO zcl_class.
CREATE OBJECT lo_class.

lo_calss -> static_name = '001'.
zcl_class => static_name = '002'.

跟这个手动声明的CLASS-DATA一样的。注意就是它只能在PUBLIC里面。

CLASS zcl_class DEFINITION.
  PUBLIC SECTION.
    CLASS-DATA:
     static_name TYPE String.
ENDCLASS.

常量属性。要附初始值。就是自己手动写的时候那个CONSTANTS.
除此之外,还有个可视:
在这里插入图片描述
public 就是数据在任何类和程序都可以访问。属性一般弄成public,方法一般弄成public.
protected 在类本身,类子类,类友元中可见。一般属性都是私有或者保护的。类有个共有的set和get方法对属性进行存取,保证数据格式和合法性验证。
private 类本身和类友元可见。
在这里插入图片描述
Read Only的话,是对外read only。类自己的方法还是可以改它的属性的。就算是public了,也不能被外面修改。
在这里插入图片描述
属性的定义方式。
LIKE跟着已经实例化的数据变量或者对象。
TYPE后面是数据类型,或者SE11里面的表的字段啥的。
TYPE REF TO类。
TYPE BOXED 嵌套结构。
在这里插入图片描述
在这里插入图片描述

参照已有或者自己代码types定义。
或者在TYPES里面也能看到代码里定义的type。
在这里插入图片描述
方法 就是说类的功能。有了数据再有了功能才能实现。
类的方法就是类对象的状态改变和消息传递的行为方式。代表类对象可以被外部执行的活动。也就是被外部程序调用。
类方法的设计一般功能最小化单一原则。一个方法只处理一件事。代码行数不超过一屏。
方法包括实例方法和静态方法。实例方法必须通过类的实例来使用。
静态方法就相当于全局方法,不属于类的对象而属于全局类。静态方法主要用来对应操作它的静态属性。用类=> 或者对象->来调用。
在这里插入图片描述
静态方法里只能调用类的其他静态方法,访问类的静态属性数据。public和protected的静态方法可以被子类继承,但静态方法不可以在子类中被重新定义。
类的构造器是静态方法,对象构造器是实例方法。
CLASS_CONSTRUCTOR Static Method
CONSTRUCTOR Instance Method

插入
传引用和传值的区别
在方法参数中,不勾就是传引用。引用就是变量的存放地址。方法内的参数变量和方法外的实际变量共享地址内的值。方法内进行值改变,方法外的值也改变。
在这里插入图片描述
如果是returning那就是传一个值了,默认是pass value钩上的。
如果是传值,意思是将数据的值复制一份到另一个地址里,然后把值传入方法中。
插入结束

事件 就是说通过程序触发一个事件,然后来执行一个方法。
事件没代码,可以有参数。
在这里插入图片描述
建事件之后,建方法。建了方法进去把它设置在事件后运行。把Event Handler for 打钩,然后填写类和event。
在这里插入图片描述
也就是说当这个event被触发,那么这个方法就会自动执行。
Method Type里面就是用来标识这些的:
在这里插入图片描述
那么event就是用RAISE EVENT去写了。

8.4.4 接口

接口是啥呢?用来干啥的呢?
当两个相似的类有个同名的方法,但是不同的功能。就上接口了。
接口有点像类,但是接口中的方法是在类中实现的,是对类的扩展。实现接口后,接口将成为类的公有成员,接口加上继承,是多态的基础。就是说啥呢?
在一个接口中定义的方法在不同类中有不同的实现,接口没有自己的实例, 因而也不需要进行方法实现。

INTERFACE <intf_name>. 
DATA..... 
CLASS-DATA..... 
METHODS..... 
CLASS-METHODS..... 
ENDINTERFACE.
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaomici

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值