枚举对象是枚举类型的数据对象。枚举对象只能包含类型为枚举类型的枚举值。ABAP从版本7.51开始支持它们。

这是一种常见的模式。在ABAP 7.51之前,人们通常用如下方式实现类似的功能:

CLASS cx_wrong_size DEFINITION INHERITING FROM cx_static_check.
ENDCLASS. CLASS shirt DEFINITION.
PUBLIC SECTION.
TYPES tsize TYPE i.
CONSTANTS:
size_s TYPE tsize VALUE ,
size_m TYPE tsize VALUE ,
size_l TYPE tsize VALUE ,
size_xl TYPE tsize VALUE .
METHODS
constructor IMPORTING size TYPE tsize
RAISING cx_wrong_size.
...
PRIVATE SECTION.
DATA
size TYPE tsize.
ENDCLASS. CLASS shirt IMPLEMENTATION.
METHOD constructor.
IF size <> size_s AND
size <> size_m AND
size <> size_l AND
size <> size_xl.
RAISE EXCEPTION TYPE cx_wrong_size.
ENDIF.
me->size = COND #(
WHEN size <> size_s AND
size <> size_m AND
size <> size_l AND
size <> size_xl THEN THROW cx_wrong_size( )
ELSE size ).
ENDMETHOD.
ENDCLASS.

这里,size属性只可以是shirt类中定义的常量中的值。其它值会导致异常。用户创建shirt类时,需要这样做:

TRY.
DATA(shirt) = NEW shirt( shirt=>size_xl ).
CATCH cx_wrong_size.
...
ENDTRY.

看到开销了吗?为什么不让运行时环境来为你做值检查呢?有一种叫做枚举和枚举类型的概念(可以在这种情况下应用)。

在7.51以及更高的版本里,ABAP也会支持枚举概念。如果使用枚举类型来重写上面的例子的话:

CLASS shirt DEFINITION.
PUBLIC SECTION.
TYPES:
BEGIN OF ENUM tsize,
size_s,
size_m,
size_l,
size_xl,
END OF ENUM tsize.
METHODS
constructor IMPORTING size TYPE tsize.
...
PRIVATE SECTION.
DATA
size TYPE tsize.
ENDCLASS. CLASS shirt IMPLEMENTATION.
METHOD constructor.
me->size = size.
ENDMETHOD.
ENDCLASS.

TYPES语句的一个新变式:BEGIN OF ENUMEND OF ENUM,它可以围起一个常量的集。常量的标准基本类型是i并且枚举值从0开始计数。

像上文那样使用的话:

DATA(shirt) = NEW shirt( shirt=>size_xl ).

不过,使用了枚举对象后,你不再需要处理异常了。如果你传递一个非法值的话,会得到语法错误!

DATA(shirt) = NEW shirt(  ).

枚举是类型和常量的混合体。通过BEGIN OF ENUM enum – END OF ENUM enum 你声明了一个可以在TYPE附加项后声明的基本类型enum。在它们之间,你可以声明一个常量集,它们叫做枚举常量。这样就定义了拥有enum类型的枚举对象所允许的枚举值。在这里,TYPES实际上就和CONSTANTS语句一样。

ABAP运行时环境会检查只有被允许的枚举值可以被赋给枚举对象。

TYPES:
BEGIN OF ENUM tsize,
size_s,
size_m,
size_l,
size_xl,
END OF ENUM tsize. DATA size TYPE tsize.
size = size_xl. "允许 DATA dobj LIKE size.
dobj = size. "允许 dobj = . "语法或运行时错误

枚举对象只能赋值给拥有相同枚举类型的枚举对象。同样,枚举对象间的比较也只能在相同类型的枚举对象间发生。当然,枚举常量本身也包含在内。

通常,你一点也不关心枚举对象的内容。枚举对象的语义由枚举常量来定义。然而,你也可以将枚举类型定义为i类型之外的其它基本类型,并且拥有其它枚举值(其中一个必须是初始值):

TYPES:
basetype TYPE c LENGTH ,
BEGIN OF ENUM tsize BASE TYPE basetype,
size_i VALUE IS INITIAL,
size_s VALUE `S`,
size_m VALUE `M`,
size_l VALUE `L`,
size_xl VALUE `XL`,
END OF ENUM tsize. DATA size TYPE tsize.
size = size_xl. "允许 DATA dobj LIKE size.
dobj = size."允许

这使你可以轻松地把现有“枚举值”转换为新方式的枚举值。运气好的话,可以不需要调整它们的使用。

如果你在一个上下文中有超过一个枚举类型,你可以将各个枚举值组织到结构里:

TYPES:
BEGIN OF ENUM tsize STRUCTURE size,
s,
m,
l,
xl,
END OF ENUM tsize STRUCTURE size. DATA dobj TYPE tsize.
dobj = size-xl. "允许

以上代码定义了一个枚举结构size。结构的组件是枚举类型的枚举常量。

枚举对象的常见用处是比较它和枚举常量以决定程序需要切换到哪一个功能分支:

TYPES:
BEGIN OF ENUM tsize STRUCTURE size,
s,
m,
l,
xl,
END OF ENUM tsize STRUCTURE size. DATA dobj TYPE tsize. ... CASE dobj.
WHEN size-s.
...
WHEN size-m.
...
WHEN size-l.
...
WHEN size-xl.
...
ENDCASE.

除此之外,还有一些可以应用的情况:

你可以将枚举对象赋给一个c类型或者string类型的文本。结果就是定义了枚举值的枚举常量的名字。

TYPES:
BEGIN OF ENUM tsize,
size_s,
size_m,
size_l,
size_xl,
END OF ENUM tsize. DATA text TYPE string.
text = size_xl.
cl_demo_output=>display( text ). "结果是SIZE_XL

也可以写作:

DATA(text) = CONV string( size_xl ).

可以使用CONV操作符指定类型来访问当前值:

TYPES:
BEGIN OF ENUM tsize,
size_s,
size_m,
size_l,
size_xl,
END OF ENUM tsize. DATA(value) = CONV i( size_xl ) .
cl_demo_output=>display( value ). "输出结果是3

另一种方式是,可以使用CONV将一个有效的枚举值转换为枚举对象(常规的赋值语句是无法做到的):

TYPES:
BEGIN OF ENUM tsize,
size_s,
size_m,
size_l,
size_xl,
END OF ENUM tsize. DATA(num) = . TRY.
DATA(dobj) = CONV tsize( num ) .
cl_demo_output=>display( dobj ). "Output is SIZE_XL
CATCH cx_sy_conversion_no_enum_value.
...
ENDTRY.

RTTI中也多了一个相应的类CL_ABAP_ENUMDESCR

TYPES:
BEGIN OF ENUM tsize,
size_s,
size_m,
size_l,
size_xl,
END OF ENUM tsize. DATA(size) = VALUE tsize( ). DATA(enum_descr) = CAST cl_abap_enumdescr(
cl_abap_typedescr=>describe_by_data( size ) ). cl_demo_output=>new(
)->write_data( enum_descr->kind "E, for elementary
)->write_data( enum_descr->type_kind "k, new for enumerated type
)->write_data( enum_descr->base_type_kind "I, the base type
)->write_data( enum_descr->members "Table of constants and values
)->display( ).

基本上就是这些内容了。

躺下让ABAP运行时来为你工作吧。要注意枚举类型只能在某些合适的运算位置中出现,并且只能包含预先规定的值。非法的枚举值永远不会在枚举对象中出现。

PS:原文的评论中有人提到,枚举值和数据字典中的domain的固定值很像,为什么二者没有集成关系?

作者的回答是:这个特性实际上已经在设计中了,很有希望出现。具体情况要视资源和优先级而定。

本文链接:http://www.cnblogs.com/hhelibeb/p/7976078.html

英文原文:ABAP News for Release 7.51 – Enumerations

ABAP中的枚举对象的更多相关文章

  1. java 根据值获取枚举对象

    关键方法: /** * 值映射为枚举 * * @param enumClass 枚举类 * @param value 枚举值 * @param method 取值方法 * @param <E&g ...

  2. JS基础_枚举对象中的属性

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  3. 枚举对象中的属性 for . . in

    枚举对象中的属性:把对象中所有的属性和值都取出来 使用 for . . . in 语句 语法: for(var  变量  in  对象){ } for  . . . in 语句  对象中有几个属性,循 ...

  4. 第三章 EnumUtil根据值获取枚举对象

    项目中使用枚举类的好处这里不再赘述,在使用枚举值时,通常需要根据值来获取枚举对象,下面介绍两种实现方案: 1.在枚举类中定义方法实现 首先给出如下性别枚举类: public enum SexEnum ...

  5. 【译】Java中的枚举

    前言 译文链接:http://www.programcreek.com/2014/01/java-enum-examples/ Java中的枚举跟其它普通类很像,在其内部包含了一堆预先定义好的对象集合 ...

  6. 重温WCF之数据契约中使用枚举(转载)(十一)

    转载地址:http://www.zhuli8.com/wcf/EnumMember.html 枚举类型的定义总是支持序列化的.当我们定义一个新的枚举时,不必应用DataContract特性,就可以在数 ...

  7. 说说Java中的枚举(一)

    在实际编程中,往往存在着这样的“数据集”,它们的数值在程序中是稳定的,而且“数据集”中的元素是有限的.例如星期一到星期日七个数据元素组成了一周的“数据集”,春夏秋冬四个数据元素组成了四季的“数据集”. ...

  8. 字符串处理:ABAP中的正则表达式

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  9. ruby中迭代器枚举器的理解

    参考<ruby编程语言>5.3迭代器和可枚举对象 迭代器一个迭代器是一个方法,这个方法里面有yield语句,这个方法里的yield语句,与传递给这个方法的块进行数据传输 yield将数据传 ...

随机推荐

  1. HTML5浏览器端图片预览&生成Base64

    本文主要介绍如何通过拖拽方式在浏览器端实现图片预览,并生成图片的Base64编码. 工具链接:图片转Base64. 首先介绍一下FileReader, FileReader对象允许浏览器使用File或 ...

  2. 项目实战4—haproxy 负载均衡和ACL控制

     haproxy实现高级负载均衡实战 环境:随着公司业务的发展,公司负载均衡服务已经实现四层负载均衡,但业务的复杂程度提升,公司要求把mobile手机站点作为单独的服务提供,不在和pc站点一起提供服务 ...

  3. Iptables详解七层过滤

    <Iptables详解七层过滤> 一.防火墙简介 防火墙其实就是一个加固主机或网络安全的一个设备或者软件而已,通过防火墙可以隔离风险区域与安全区域的连接,同时不会妨碍风险区域的访问.当然需 ...

  4. linux 常用命令详解

    常见Linux目录名称:/ 虚拟目录的根目录.通常不会在这里存储文件/bin 二进制目录,存放许多用户级的GNU工具/boot 启动目录,存放启动文件/dev 设备目录,Linux在这里创建设备节点/ ...

  5. CCF-201512-2-消除类游戏

    问题描述 试题编号: 201512-2 试题名称: 消除类游戏 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 消除类游戏是深受大众欢迎的一种游戏,游戏在一个包含有n行m列的游 ...

  6. javascript设计模式——发布订阅模式

    前面的话 发布—订阅模式又叫观察者模式,它定义对象间的一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知.在javascript开发中,一般用事件模型来替代传统的发布—订阅模 ...

  7. UPDATE/INSERT用法研究

    UPDATE和INSERT语法相信大家都很熟悉,UPDATE的基本语法结构是 : UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值 INSERT的基本语法是: INSERT ...

  8. 升级安装php7要考虑的几个方面

    php7从推出到现在,前两天官方已经发布到7.2版本,把自己升级和安装php7中遇到的问题和解决方法做一个笔记,内容主要包括:1) mysql2) php3) nginx4) memcache扩展5) ...

  9. 出现JSONvalue failed .error is Illegal start of token

    出现JSONvalue failed .error is Illegal start of token了? 别着急,抽根烟,喝杯水.开工: 1:判断是请求前报的错还是请求后报的错!!这个很重要,我就是 ...

  10. Git~GitLab当它是一个CI工具时

    CI我们都知道,它是持续集成的意思,主要可以自动处理包括编译,测试,发布等一系列的过程,而GitLab也同样包含了这些功能,我们可以通过pipeline很容易的实现一个软件从编译,测试,发布的自动化过 ...