天天看點

ABAP中的枚舉對象

枚舉對象是枚舉類型的資料對象。枚舉對象隻能包含類型為枚舉類型的枚舉值。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 ENUM – END OF ENUM,它可以圍起一個常量的集。常量的标準基本類型是i并且枚舉值從0開始計數。

像上文那樣使用的話:

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

不過,使用了枚舉對象後,你不再需要處理異常了。如果你傳遞一個非法值的話,會得到文法錯誤!

DATA(shirt) = NEW shirt( 333 ).      
ABAP中的枚舉對象

枚舉是類型和常量的混合體。通過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 = 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

繼續閱讀