自学内容网 自学内容网

ABAP开发-面向对象开发_1

系列文章目录



前言


一、概述

接触一块新知识,首先要了解清楚他的基本概念、作用、特点,明白他究竟是用来干什么的,而不是埋头苦写代码,了解清楚基本的术语之后,再接手代码思路会清晰很多,也会知道自己写程序是为了干什么,而不是稀里糊涂的没报错就万事大吉。

  • 从SAP R/3 4.0版本开始,ABAP就引入了面向对象的开发概念
  • ABAP语言的发展
    • 宏编译器
    • ABAP语言-面向过程
    • ABAP语言-面向对象,ABAP对象是ABAP的扩展,集合了JAVA,C++,SMALLTALK等语言的特点,与原来的ABAP无缝集成
  • 面向对象解决方法中,重点放在了对现实生活中的对象 结构化抽象化(学过C++的对此应该深有体会)
    • 属性ATTRIBUTES:对象的属性及其特征
    • 方法METHODS:定义对象的行为
  • 类的优点
    • 可重复利用代码
    • 可封装数据

二、面向对象开发特点

  • 抽象

    • 实现客观世界实体的模块化
    • 将复杂的业务逻辑和数据结构简化为易于理解和管理的类。通过抽象,开发者可以忽略对象的内部实现细节,而只关注其对外提供的接口和功能,也有助于降低系统的复杂性,提高代码的可读性和可维护性。
  • 封装

    • 是面向对象编程的第一特征, 把客观事物封装成抽象的类,并对外提供有限的访问接口(可以把自己的数据和方法只让可信的类或对象操作,对不可信的进行信息隐藏)
    • 有助于隐藏内部实现细节,保护数据不被外部随意访问和修改,从而增强了系统的安全性和稳定性。同时,它也使得类的内部实现更加灵活,可以在不改变外部接口的情况下进行内部优化和重构
  • 继承

    • 允许一个类(子类)继承另一个类(父类)的属性和方法。可以使用现有类的所有功能(即继承了原来的),并在无需重新编写原来的类的情况下对这些功能进行扩展
    • 继承通过定义子类并指定其继承自哪个父类来实现。子类可以继承父类的所有公共和受保护属性和方法,并可以在此基础上进行扩展或重写
    • 有助于提高代码的复用性和可扩展性,但也可能导致类之间的依赖关系变得复杂,因此在设计时需要谨慎考虑继承层次和关系
  • 多态

    • 指不同类的对象可以通过相同的接口来调用相同的方法,但具体实现可以不同
    • 允许将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给他的子对象的特性以不同的方式运作,简单地说,就是:允许将子类类型的指针赋值给父类类型的指针

三、类与对象

类CLASS
(1)类是创建对象的模板。它定义了对象可以包含的数据(属性)以及对象可以执行的操作(方法)。在ABAP中,定义一个类需要包含定义(DEFINITION)和实现(IMPLEMENTATION)两部分。
(2) 类的区分

  • 全局类Global:TCOED:SE24
    • 存储在类池中
    • 所有ABAP程序都可以对其进行访问
  • 本地类Local
    • 在程序中定义
    • 只有该程序可以使用

(3) 程序中类的创建(即一个类可以包含的部分)

  • 定义类----属性、方法、事件
    • CLASS < CLASS > DEFINITION
      • 要素申明
      • 所有项目都需要定义在三个访问区域之一中
    • ENDCLASS
  • 实现类----包含方法的具体实现代码,定义了当对象调用方法是=时应执行的操作
    • CLASS < class > IMPLEMENTATION
    • ENDCLASS

(4) 访问区域
定义了类组件(属性、方法等)的可见性和可访问性,ABAP中的类可以包含三个访问区域:公共部分、受保护部分、私有部分

  • 公共部分Public Section
    • 内部可见,外部可见
    • 在公共部分声明的所有组件对类的所有用户以及继承自它的类的方法是可以访问的
    • 类的公共组件构成了类与其用户之间的接口
    • 如果想从类的外部访问某个组件,应该将该组件声明在公共部分
  • 受保护部分Protected Section
    • 内部可见,继承可见,外部不可见
    • 类的受保护组件构成继承类之间的接口
  • 私有部分Private Section
    • 内部可见,继承不可见,外部不可见
    • 私有组件被封装在类内部,只能通过类自己的方法来访问和修改

(5)类构成要素

  • 构成要素的分类
    • 实例组件
      • 参照类创建对象时,内存中存在的项目,每次创建对象时都会被初始化,各个类的对象中都存在
      • 声明方式:属性----DATA,方法----METHODS;访问:OBJECT->COMP
    • 静态组件
      • 遇到创建类的语句(CREATE OBJECT)开始,直到程序结束都存储在内表中,是依赖类存在的项目,即使不创建对象,若已存在于内存中即可直接使用
      • 声明方式:属性----CLASS-DATA,方法----CLASS-METHODS;访问:CLASS->COMP
  • 类的所有要素在声明部分实现
    • 属性(Attributes):是类的成员变量,表示对象的状态或数据,可以拥有ABAP所有数据类型的类内部数据字段,对象状态由属性决定

    • 方法(Methods):是类的成员函数,用于定义对象的行为或操作,可以访问类的所有属性,可通过方法修改对象的内容,另外,方法提供传入传出参数,便于用户交互

      • 方法定义的基本语句
        METHOD < meth >
        IMPORTING …< i1 > TYPE < type >…
        EXPORTING …< e1 >TYPE < type >…
        CHANGING …< c1 >TYPE < type >…
        EXCEPTIONS …X1…
      • CALL METHOD [oref->|class=>]meth
        EXPORTONG …i1 = f1…
        RECEIVING R = h.

      IMPORT/EXPORT:数据输入/输出接口,接口参数可以参考单个变量,结构或内表
      CHANGING:同时作为输入/输出接口,接口参数可以参考单个变量,结构或内表
      RETURNING:返回类传递数值,该定义不能和CHANGING/EXPORTING同时使用
      EXCEPTIONS:返回执行中所出现的错误

      • 类函数可以拥有多个输入参数,但只能有一个输出参数。类的输出接口参数必须与类函数中所定义类型保持一致

      • 方法的调用
        当方法没有输出参数(EXPORTING)的时候可以通过以下方式调用
        CALL METHOD meth()."没有输入参数
        CALL METHOD meth( a )."一个输入个输入
        CALL METHOD meth( f1 = a1…fn = an)."n

      • 构造方法

        • 在实例化对象时,自动完成对象的初始化,并且这个对象是空的
        • 若希望每一个对象都为其初始化某些特征,需要用到构造方法
        • 没有返回数据类型,功能是在实例化类时完成一些初始化工作
        • 使用METHODS CONSTRUCTOR定义
        • 或使用CLASS-METHODS CLASS_CONSTRUCTOR定义
        • 每个类只能有一个构造方法,在CREATE OBJECT语句中自动调用构造方法
      • 什么时候使用构造方法

        • 需要分配外部资源
        • 需要初始化一些不能用DATA语句的VALUE指定的属性值
        • 需要修改静态属性
        • 通常不能显示的调用构造器
    • 事件(Events):是类可以触发或响应的事件,是没有继承关系的类之间可以互相调用彼此方法的特殊方法

属性类型ABAP语句
实例属性DATA
静态属性CLASS-DATA
方法类型ABAP语句
实例属性METHODS
静态属性CLASS-METHODS
特殊方法CONSTRUCTOR
事件ABAP语句
事件声明EVENTS EVT EXPPRTING…VALUE(e1 e2)TYPE
调用事件RAISE EVENT EVT EXPORTING e1 = f1 e2 = f2…
Event Handler声明METHODS meth FOR EVENT evt OF cif IMPORTING e1 e2
Event Handler 注册/登陆SET HANDLER h1 h2[FOR]…

对象OBJECT
对象是类的实例,每个对象多有自己固定的属性,一个类可以创建多个对象,在ABAP中程序要访问对象,需要使用参照对象(Object Reference),参照对象始终存在于参照对象变量中 ---- Data obj TYPE REF TO class。
对象是根据类模板创建的具体实体,具有类定义的所有属性和方法。在ABAP中,创建对象的过程称为实例化。
eg:类(模板)-》对象(实例)-》属性DATA—家庭资产、方法METHOD—发工资-》方法会影响属性

  • 对象实例化
    使用CREATE OBJECT语句来创建对象。例如,如果有一个名为book的类,可以使用CREATE OBJECT book1来创建该类的一个实例,命名为book1
  • 访问对象的属性和方法
    通过对象实例名和箭头符号(->)来访问对象的属性和方法。例如,book1->title访问book1对象的title属性,book1->print_info()调用book1对象的print_info方法。

四、实例

定义一个名为LCL_FATHER的父类,实现该父类,定义该父类的两个对象,对象实例化,调用对象的属性和方法;
定义一个继承LCL_FATHER的子类LCL_SON,实现该子类,定义该子类的对象,对象实例化,调用对象的属性和方法

*&---------------------------------------------------------------------*
*& Report ZYT36_DAY9_36130
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ZYT36_DAY9_36130.
"类-》实例:实例化的过程
*创建两个本地的类
*父类/子类
*本地(local)的类作用域--当前程序

*第一个类--父类
*类的定义
*类的定义里面包含
*类都有哪些属性,方法(只有方法的名字和参数,不包含实现逻辑),以及这些属性和方法属于哪个访问区域
CLASS LCL_FATHER DEFINITION."类的定义关键字CLASS-类名字-DEFINITION
*类的定义放到CLASS和ENDCLASS中间

*公开的部分
PUBLIC SECTION."公开的区域:这里面的属性和方法,所有人都可见
*公开的属性
DATA:"定义实例(OBJECT)属性,每个实例都有自己独特的值,一个一个的父亲就是一个一个的实例
      GV_FIRST_NAME TYPE C LENGTH 4,
      GV_LAST_NAME TYPE C LENGTH 4.
CLASS-DATA:"静态属性:父亲这个类的属性
      GV_GENDER TYPE C VALUE 'M'.
*公开的方法
METHODS:
*构造函数
CONSTRUCTOR IMPORTING IV_ID TYPE I,"构造函数
SET_NAME IMPORTING IV_FIRST_NAME TYPE STRING"IV_FIRST_NAME、IV_LAST_NAME是两传入的参数
                   IV_LAST_NAME TYPE STRING,
GET_NAME,"没有传入参数

GET_MONEY RETURNING VALUE(RV_MONEY) TYPE I,"对外的方法,可以告诉别人家庭资产
FAGONGZI IMPORTING IV_MONEY TYPE I."发工资,增加家庭资产  方法的名字-IMPORTING-传入参数的名字IV_MONEY(I:传入的,V:变量)

*受保护的部分
PROTECTED SECTION."受保护:自己和子类可见,外面不可见

DATA:
      GV_FAMILY_MONEY TYPE I,"家庭的共有财产
      GV_ID TYPE I."ID
METHODS:
      GET_FAMILY_MONEY RETURNING VALUE(RV_MONEY) TYPE I."自己看看自己的家庭财产

*私有部分:只有自己可见
PRIVATE SECTION.
DATA:
      GV_MY_MONEY TYPE I."私房钱
METHODS:
      ADD_SIFANG_QIAN IMPORTING IV_MONEY TYPE I,"增加私房钱,IMPORTING传入参数IV_MONEY
      GET_SIFANG_QIAN RETURNING VALUE(RV_MONEY) TYPE I."得到我一共有多少私房钱RETURNING返回值,返回参数RV_MONEY(R:返回的,V:变量)

ENDCLASS.
*类的实现
*实现方法的具体逻辑,实现是实现什么,是实现定义里的方法,另外:属性是通过方法来访问的
CLASS LCL_FATHER IMPLEMENTATION.
*类的实现

*构造函数:当用类去创建对象的时候,会自动调用构造函数
METHOD CONSTRUCTOR.
  GV_ID = IV_ID."给当前实例的属性赋值
  WRITE: / '调用构造函数,给ID赋值', GV_ID.
  ENDMETHOD.

METHOD SET_NAME.
  GV_FIRST_NAME = IV_FIRST_NAME."用传入的NAME给属性赋值
  GV_LAST_NAME = IV_LAST_NAME.
  WRITE: / '调用SET_NAME给名字赋值'.
  ENDMETHOD.

METHOD GET_NAME.
  WRITE: / '我的名字是:',GV_FIRST_NAME,GV_LAST_NAME.
  ENDMETHOD.

METHOD GET_MONEY."对外的方法,告诉别人自己家庭有多少钱
    RV_MONEY = GV_FAMILY_MONEY - 200."将家庭资产(实打实赋值或隐藏部分)赋值给该方法要返回的参数
  ENDMETHOD.

METHOD FAGONGZI.
  "传入参数IV_MONEY
  "当发的工资大于100时一部分计入私房钱,一部分计入家庭资产,否则全部计入家庭资产
  IF IV_MONEY > 100.
ADD_SIFANG_QIAN( IV_MONEY = 100 )."调用ADD_SIFANG_QIAN方法,执行ADD_SIFANG_QIAN方法,那么私房钱就增多了
  GV_FAMILY_MONEY = GV_FAMILY_MONEY + IV_MONEY - 100.
  ELSE.
     GV_FAMILY_MONEY = GV_FAMILY_MONEY + IV_MONEY.
  ENDIF.
  ENDMETHOD.

METHOD GET_FAMILY_MONEY.
  RV_MONEY = GV_FAMILY_MONEY."通过方法来访问类里面的属性,  RV_MONEY 是传出参数
  ENDMETHOD.

METHOD ADD_SIFANG_QIAN.

   GV_MY_MONEY =  GV_MY_MONEY + IV_MONEY.
  ENDMETHOD.

METHOD GET_SIFANG_QIAN.
  RV_MONEY = GV_MY_MONEY.
  ENDMETHOD.
ENDCLASS.



*定义一个子类LCL_SON继承父类LCL_FATHER
*所有父类的PUBLIC和PROTECTED的方法/属性,子类都自动拥有
CLASS LCL_SON DEFINITION INHERITING FROM LCL_FATHER.

  PUBLIC SECTION.
  DATA:
        GV_SCHOOL TYPE C LENGTH 20."所有父类PUBLIC里面有的都会被自动继承,不需要重复定义
                                   "在子类里可以添加子类独有的属性和方法
  METHODS:
    "GET_MONEY."父类已经有了,子类就不能定义了
    GET_SCHOOL,
    SHOPPING.

  PROTECTED SECTION.
    DATA:
          LING_HUA_QIAN TYPE I."定义儿子的特有属性
    METHODS:
    GET_FAMILY_MONEY REDEFINITION."对父类的方法进行重定义!
  ENDCLASS.

CLASS LCL_SON IMPLEMENTATION."对儿子的方法进行实现 ,父类有的方法自动继承,无需重复实现
  METHOD GET_SCHOOL.
    WRITE: / '我的学校是:',GV_SCHOOL.
    ENDMETHOD.

  METHOD SHOPPING.
    GET_FAMILY_MONEY( ).
    WRITE: / '最多能花',LING_HUA_QIAN.
    ENDMETHOD.

  METHOD GET_FAMILY_MONEY.
    "RV_MONEY = GV_FAMILY_MONEY."1
    SUPER->GET_FAMILY_MONEY( )."2  可以用SUPER关键字来调用父类的方法
    LING_HUA_QIAN = GV_FAMILY_MONEY * '0.1'."先调用父类的方法(走到父类的方法实现里面去)(做一些通用的处理),再实现子类自己的逻辑(子类自己需要干的事情)
    ENDMETHOD.
  ENDCLASS.

START-OF-SELECTION.
*怎么调用CLASS
*1、定义变量  (对象)
DATA: LO_F_1 TYPE REF TO LCL_FATHER."用本地定义的类来声明一个对象   DATA定义一个变量 ,TYPE REF TO定义一个指针类型的关键字,后面跟着CLASS的名字


*2、对象的实例化 用CREATE OBJECT将对象实例化
CREATE OBJECT LO_F_1"创建对象的时候,会自动调用构造函数,因为我们的构造函数有一个传入参数,所以要调用传入参数,若没有参数,则直接CREATE OBJECT LO_F_1
EXPORTING
  IV_ID = 1.

*3、调用对象的属性和方法
*对象名字LO_F_1->方法名字SET_NAME
*方法参数:定义时候用IMPORTING-》这里调用的时候就用EXPORTING引用;定义时候用EXPORTING-》这里用IMPORTING
LO_F_1->SET_NAME(
EXPORTING
  IV_FIRST_NAME = '张'
  IV_LAST_NAME = '三'
).

LO_F_1->GET_NAME( ).

*4、验证调用属性
*4.1实例的属性
WRITE: / '直接调用实例属性:',LO_F_1->GV_FIRST_NAME.
*4.2静态属性
WRITE: / '实例调用静态属性:',LO_F_1->GV_GENDER."CLASS-DATA这个关键字定义的是静态属性
WRITE: / '类调用静态属性:',LCL_FATHER=>GV_GENDER."CLASS-DATA这个关键字定义的是静态属性,只有静态属性可以用CLASS=>属性名

*5、练习:发工资--》查看家庭资产和私房钱是否有变化
LO_F_1->FAGONGZI(
EXPORTING
  IV_MONEY = 8000
  ).
*得到家庭资产
*DATA(LV_FAMILY_MONEY) = LO_F_1->GET_FAMILY_MONEY( )."LV_FAMILY_MONEY来接收传出的参数 "因为这个方法是protected,在外面不可以访问
DATA(LV_MONEY) = LO_F_1->GET_MONEY( )."GET_MONEY方法里传出来的参数赋给新定义的LV_MONEY
WRITE: / '当前家庭资产是:',LV_MONEY.
*DATA(LV_MONEY1) = LO_F_1->GET_SIFANG_QIAN( )."因为这个方法是PRIVATE,在外面不可以访问


WRITE: / '----------------------------------------'.


*创建实例化LO_F_2  李四 6000
DATA: LO_F_2 TYPE REF TO LCL_FATHER.

CREATE OBJECT LO_F_2
EXPORTING
  IV_ID = 2.

*SET_NAME
LO_F_2->SET_NAME(
EXPORTING
  IV_FIRST_NAME = '李'
  IV_LAST_NAME = '四'
).
LO_F_2->FAGONGZI(
EXPORTING
  IV_MONEY = 6000
  ).
DATA(LV_MONEY2) = LO_F_2->GET_MONEY( ).
WRITE: / '当前家庭资产是:',LV_MONEY2.


WRITE: / '----------------------------------------'.


DATA: LO_SON_1 TYPE REF TO LCL_SON.
 CREATE OBJECT LO_SON_1
 EXPORTING
   IV_ID = 1.

LO_SON_1->GV_SCHOOL = '希望中学'.
*调用从父类继承来的方法
 LO_SON_1->SET_NAME(
 EXPORTING
   IV_FIRST_NAME = '李'
   IV_LAST_NAME = '五'
   ).
 LO_SON_1->GET_NAME( ).

 LO_SON_1->FAGONGZI(
 IV_MONEY = 1000
 ).

 LO_SON_1->SHOPPING( ).

执行结果:
在这里插入图片描述



原文地址:https://blog.csdn.net/weixin_52203666/article/details/143750281

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!