1. 程式人生 > >ABAP中的枚舉對象

ABAP中的枚舉對象

結構 src 轉換 操作 之間 exception version exc put

枚舉對象是枚舉類型的數據對象。枚舉對象只能包含類型為枚舉類型的枚舉值。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
0, size_m TYPE tsize VALUE 1, size_l TYPE tsize VALUE 2, size_xl TYPE tsize VALUE 3. 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( 333 ).

技術分享圖片

枚舉是類型和常量的混合體。通過BEGIN OF ENUM enumEND 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 = 333. "語法或運行時錯誤

枚舉對象只能賦值給擁有相同枚舉類型的枚舉對象。同樣,枚舉對象間的比較也只能在相同類型的枚舉對象間發生。當然,枚舉常量本身也包含在內。

通常,你一點也不關心枚舉對象的內容。枚舉對象的語義由枚舉常量來定義。然而,你也可以將枚舉類型定義為i類型之外的其它基本類型,並且擁有其它枚舉值(其中一個必須是初始值):

TYPES:
  basetype TYPE c LENGTH 2,
  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) = 3.

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中的枚舉對象