Você está na página 1de 14

Using RTTS to avoid runtime errors while attempting to downcast:

RTTS stands for RunTime Type Services. RTTS is made of 2 components:


RTTI (RunTime Type Identification) is used to identify the type of the object that is being pointed
to by a reference variable.
RTTC (RunTime Type Creation) is used for dynamic creation of structures, internal tables and
other objects.
RTTI and RTTC may be called using methods in CL_ABAP_xxxDESCR classes. Each of these classes
have both RTTI and RTTC methods.
To avoid runtime errors that may occur while attempting to downcast, we must first indentify the actual
type (Reference type, i.e. the name of the class) of the object that is currently being pointed to by the
reference variable that we are attempting to downcast. In this regard, there are two important predefined
classes in SAP which help us identify the class name of an object at runtime. These classes are:
1. CL_ABAP_TYPEDESCR
2. CL_ABAP_CLASSDESCR
These two classes are related through the inheritance hierarchy as depicted below:
CL_ABAP_TYPEDESCR
CL_APAB_OBJECTDESCR
CL_ABAP_CLASSDESCR
Two important methods of the class CL_ABAP_TYPEDESCR are:
1. A class method describe_by_object_ref. This method accepts any reference variable as import
parameter and returns an object of the same class, i.e. of type CL_ABAP_TYPEDESCR.
2. An instance method get_relative_name. This method has no parameters but returns a string
value that contains the name of class of which type the object is.
The pseudo code to check (identify) the actual type of an object before attempting to downcast a
reference is as below:
DATA: r_descr TYPE REF TO cl_abap_classdescr.
r_descr ?= cl_abap_typedescr=>describe_by_object_ref( ref_var_super ).
IF r_descr->get_relative_name( ) = '<name of the subclass in upper case>'.
ref_var_sub ?= ref_var_super.
*
--- some valid code
ENDIF.

The code below is an example to find out the name of an objects class programmatically using
RTTS classes:
CLASS lcl_a DEFINITION.
PUBLIC SECTION.
METHODS: meth_a1.
ENDCLASS.
CLASS lcl_a IMPLEMENTATION.
METHOD meth_a1.
WRITE: /3 'From meth_a1 in class lcl_a'.
ENDMETHOD.
ENDCLASS.
CLASS lcl_b DEFINITION INHERITING FROM lcl_a.
PUBLIC SECTION.
METHODS: meth_b1.
ENDCLASS.
CLASS lcl_b IMPLEMENTATION.
METHOD meth_b1.
WRITE: /3 'From meth_b1 in class lcl_b'.
ENDMETHOD.
ENDCLASS.
************************
DATA: a1 TYPE REF TO lcl_a,
b1 TYPE REF TO lcl_b,
typ_descr type ref to CL_ABAP_TYPEDESCR,
cl_name TYPE string.
START-OF-SELECTION.
CREATE OBJECT: a1, b1.
*& At the time when the below line of code gets executed the reference
*& variable a1 is pointing to an object of the class LCL_A
typ_descr = CL_ABAP_TYPEDESCR=>describe_by_object_ref( a1 ).
cl_name = typ_descr->get_relative_name( ).
WRITE /3 cl_name.
SKIP.
a1 = b1.
CLEAR b1.
*& At the time when the below line of code gets executed the reference
*& variable a1 is pointing to an object of the class LCL_B
typ_descr = CL_ABAP_TYPEDESCR=>describe_by_object_ref( a1 ).
cl_name = typ_descr->get_relative_name( ).
WRITE /3 cl_name.
The output of the above code will be:

LCL_A
LCL_B

Interfaces:
An interface is like a class definition but without any implementation of its own. All the components of an
interface are public by default. Public is the only visibility scope that is applicable to interface
components; for this reason visibility specification is not allowed in an interface definition.
The implementation can be provided in the classes that inherit from the interface. Classes that inherit
from an interface and provide the implementation are known as the implementation classes of the
interface. A class can inherit from multiple interfaces.
We can declare reference variables of an interface, but we cannot create an object of an interface. The
reference variable of an interface can hold the reference of the object of any of the classes that inherit
from the interface and provide implementation to the interface methods.
INTERFACE lif_message.
METHODS: show_message.
ENDINTERFACE.
CLASS lcl_a DEFINITION.
PUBLIC SECTION.
METHODS: meth_one.
INTERFACES: lif_message.
ENDCLASS.
CLASS lcl_a IMPLEMENTATION.
METHOD meth_one.
WRITE: /2 'From method meth_one( )'.
ENDMETHOD.
METHOD lif_message~show_message.
WRITE: /2 'From method lif_message~show_message( )'.
ENDMETHOD.
ENDCLASS.
*******************************
START-OF-SELECTION.
DATA: a1 TYPE REF TO lcl_a,
if1 TYPE REF TO lif_message.
CREATE OBJECT a1.
a1->meth_one( ).
a1->lif_message~show_message( ).
SKIP 2.
CREATE OBJECT if1 TYPE lcl_a. " OR if1 = a1.
*& The meth_one defined in the implementing class lcl_a cannot be
*& accessed through the interface lif_message reference
* if1->meth_one( ).
*& The method show_message though implemented in the class lcl_a, its
*& definition has been inherited from the interface lcl_message, hence

*& it can be accessed also through the interface reference


if1->show_message( ).
Aliasing the methods inherited from an interface in the class definition:
INTERFACE lif_message.
METHODS: show_message.
ENDINTERFACE.
CLASS lcl_a DEFINITION.
PUBLIC SECTION.
METHODS: meth_one.
INTERFACES: lif_message.
ALIASES: show_message for lif_message~show_message.
ENDCLASS.
CLASS lcl_a IMPLEMENTATION.
METHOD meth_one.
WRITE: /2 'From method meth_one( )'.
ENDMETHOD.
METHOD show_message.
WRITE: /2 'From method lif_message~show_message( )'.
ENDMETHOD.
ENDCLASS.
*******************************
START-OF-SELECTION.
DATA: a1 TYPE REF TO lcl_a,
if1 TYPE REF TO lif_message.
CREATE OBJECT a1.
a1->meth_one( ).
a1->show_message( ).
Multiple Interface Inheritance:
In ABAP multiple class inheritance is not allowed, but multiple interface inheritance is allowed. Therefore,
a single class can inherit from one or more interfaces.
INTERFACE lif_add.
METHODS: get_sum IMPORTING arg1 TYPE i
arg2 TYPE i
RETURNING value(r_sum) TYPE i.
ENDINTERFACE.
INTERFACE lif_subtract.
METHODS: get_difference IMPORTING arg1 TYPE i
arg2 TYPE i
RETURNING value(r_diff) TYPE i.
ENDINTERFACE.
CLASS lcl_arithmetic DEFINITION.

PUBLIC SECTION.
INTERFACES: lif_add,
"Inheriting from multiple interfaces
lif_subtract.
aliases: get_sum for lif_add~get_sum,
get_difference for lif_subtract~get_difference.
ENDCLASS.
CLASS lcl_arithmetic IMPLEMENTATION.
METHOD get_sum.
r_sum = arg1 + arg2.
ENDMETHOD.
METHOD get_difference.
r_diff = arg1 - arg2.
ENDMETHOD.
ENDCLASS.
***********************
START-OF-SELECTION.
DATA: arith TYPE REF TO lcl_arithmetic,
res TYPE i.
CREATE OBJECT arith.
res = arith->get_sum( arg1 = 20 arg2 = 14 ).
WRITE: /2 'Sum:', res.
res = arith->get_difference( arg1 = 20 arg2 = 14 ).
WRITE: /2 'Difference:', res.
Storing objects of different classes implementing a given interface in an internal table of the
interface type:
INTERFACE ishape.
METHODS: getarea RETURNING value(p_area) TYPE f,
getcircumference RETURNING value(p_cirf) TYPE f.
ENDINTERFACE.
* A Circle Class that inherits from interface ISHAPE
CLASS ccircle DEFINITION.
PUBLIC SECTION.
INTERFACES ishape.
ALIASES: getarea FOR ishape~getarea,
getcircumference FOR ishape~getcircumference.
METHODS: constructor IMPORTING imc_rad TYPE f,
getradius RETURNING value(p_rad) TYPE f.
PRIVATE SECTION.
DATA rad TYPE f.
CONSTANTS pi TYPE f VALUE '3.141592365359'.
ENDCLASS.
CLASS ccircle IMPLEMENTATION.

METHOD constructor.
rad = imc_rad.
ENDMETHOD.
METHOD getradius.
p_rad = rad.
ENDMETHOD.
METHOD ishape~getarea.
p_area = 2 * pi * rad.
ENDMETHOD.
METHOD ishape~getcircumference.
p_cirf = pi * rad * rad.
ENDMETHOD.
ENDCLASS.
* A Square Class that inherits from interface ISHAPE
CLASS csquare DEFINITION.
PUBLIC SECTION.
INTERFACES ishape.
ALIASES: getarea FOR ishape~getarea,
getcircumference FOR ishape~getcircumference.
METHODS: constructor IMPORTING imc_side TYPE f,
getside RETURNING value(p_side) TYPE f.
PRIVATE SECTION.
DATA side TYPE f.
ENDCLASS.
CLASS csquare IMPLEMENTATION.
METHOD constructor.
side = imc_side.
ENDMETHOD.
METHOD ishape~getarea.
p_area = side * side.
ENDMETHOD.
METHOD ishape~getcircumference.
p_cirf = 4 * side.
ENDMETHOD.
METHOD getside.
p_side = side.
ENDMETHOD.
ENDCLASS.
*****************************************************
DATA: w_shape TYPE REF TO ishape,
" Ref-var of type ishape
t_shape TYPE TABLE OF REF TO ishape. "Array of Objects of type ishape
DATA: c1 TYPE REF TO ccircle,
s1 TYPE REF TO csquare,
c2 TYPE REF TO ccircle,

s2 TYPE REF TO csquare.


DATA: descr_ref TYPE REF TO cl_abap_typedescr,
classname TYPE string,
serial
TYPE i.
DATA: area TYPE f,
cirf TYPE f.
START-OF-SELECTION.
CREATE OBJECT: c1 EXPORTING imc_rad = '2.5',
c2 EXPORTING imc_rad = '5.0',
s1 EXPORTING imc_side = '3.5',
s2 EXPORTING imc_side = '6.0'.
*& Append in any order
APPEND: s1 TO t_shape,
c2 TO t_shape,
c1 TO t_shape,
s2 TO t_shape.
serial = 0.
LOOP AT t_shape INTO w_shape.
area = w_shape->getarea( ).
cirf = w_shape->getcircumference( ).
descr_ref =
cl_abap_typedescr=>describe_by_object_ref( w_shape ).
classname = descr_ref->get_relative_name( ).
ADD 1 TO serial.
WRITE: / serial, classname.
WRITE: / 'Area
', area DECIMALS 4 EXPONENT 0.
WRITE: / 'Circumference ', cirf DECIMALS 4 EXPONENT 0.
SKIP.
ENDLOOP.
Using RTTS to check whether the class of a given object implements a particular interface or not:
INTERFACE lif_add.
METHODS: get_sum IMPORTING arg1 TYPE i
arg2 TYPE i
RETURNING value(r_sum) TYPE i.
ENDINTERFACE.
"lif_add
INTERFACE lif_subtract.
METHODS: get_difference IMPORTING arg1 TYPE i
arg2 TYPE i
RETURNING value(r_diff) TYPE i.
ENDINTERFACE.
"lif_subtract

CLASS lcl_addition DEFINITION.


PUBLIC SECTION.
INTERFACES: lif_add.
ALIASES: get_sum FOR lif_add~get_sum.
ENDCLASS.
"lcl_addition DEFINITION
CLASS lcl_addition IMPLEMENTATION.
METHOD get_sum.
r_sum = arg1 + arg2.
ENDMETHOD.
"get_sum
ENDCLASS.
"lcl_addition IMPLEMENTATION
*******************************************
START-OF-SELECTION.
DATA: ad1 TYPE REF TO lcl_addition,
intfdesc TYPE REF TO cl_abap_intfdescr,
clname TYPE string,
mesg TYPE string.
CREATE OBJECT ad1.
intfdesc ?= cl_abap_typedescr=>describe_by_name( 'LIF_SUBTRACT' ).
IF abap_true = intfdesc->applies_to( ad1 ).
WRITE /3 'implements interface LIF_SUBTRACT'.
ELSE.
WRITE /3 'does not implements interface LIF_SUBTRACT'.
ENDIF.
intfdesc ?= cl_abap_typedescr=>describe_by_name( 'LIF_ADD' ).
IF abap_true = intfdesc->applies_to( ad1 ).
WRITE /3 'implements interface LIF_ADD'.
ELSE.
WRITE /3 'does not implement interface LIF_ADD'.
ENDIF.
Friend Classes:
If a class X defines another class Y as its friend, then the class Y will have access to the private members
of class X; irrespective of whether there is any inheritance relationship between the two. The friendship is
unidirectional, i.e. in the above example only class Y will have access to private members of class X, but
class X will not have access to the private members of class Y. A given class can have multiple other
classes defined as its friends.
CLASS lcl_b DEFINITION DEFERRED.
CLASS lcl_a DEFINITION FRIENDS lcl_b.
PRIVATE SECTION.
METHODS: pvt_method.
ENDCLASS.
CLASS lcl_a IMPLEMENTATION.
METHOD pvt_method.
WRITE: /3 'From PRIVATE method of class lcl_a'.

ENDMETHOD.
ENDCLASS.

"pvt_method

CLASS lcl_b DEFINITION.


PUBLIC SECTION.
METHODS: meth_b.
ENDCLASS.
CLASS lcl_b IMPLEMENTATION.
METHOD meth_b.
WRITE: /3 'From public method of class lcl_b.'.
DATA: a TYPE REF TO lcl_a.
CREATE OBJECT a.
*& The current code in the class lcl_b can invoke private methods of
*& the class lcl_a, as the class lcl_a has defined the current class
*& lcl_b as its friend
a->pvt_method( ).
ENDMETHOD.
ENDCLASS.
********************************************
START-OF-SELECTION.
DATA b TYPE REF TO lcl_b.
CREATE OBJECT b.
b->meth_b( ).
Abstract Methods & Abstract Classes:
If in a class the definition (method declaration) is provided for a method but the implementation is not
provided, such methods are called abstract methods. In the class definition the keyword ABSTRACT
must be used declare a method as abstract.
Syntax for declaring a method to be abstract:
METHODS <method name> ABSTRACT .
If a class contains one or more such abstract methods, the class too will have to be declared as abstract.
Syntax for declaring a method to be abstract:
CLASS <class name> DEFINITION ABSTRACT.

ENDCLASS.
If a class contains one or more abstract methods, the subclasses of the abstract class will have to
redefine it and provide the necessary implementation.
If a class is not abstract (i.e. a normal class), such class is known as a concrete class. A subclass of an
abstract class that provides implementation to all the inherited abstract methods is not an abstract class
and hence is a concrete class.
We cannot create objects of an abstract class, but we can declare reference variable for an abstract
class. Such reference variables can hold the reference of an object of abstract class subclass that is a
concrete class.

CLASS lcl_2d_shape DEFINITION ABSTRACT.


PUBLIC SECTION.
METHODS: constructor IMPORTING imc_uom TYPE char3,
get_area ABSTRACT RETURNING value(r_area) TYPE i,
get_uom RETURNING value(r_uom) TYPE char3.
PRIVATE SECTION.
DATA: uom TYPE char3. "Unit of Measurement
ENDCLASS.
"lcl_2d_shape DEFINITION
CLASS lcl_2d_shape IMPLEMENTATION.
METHOD constructor.
uom = imc_uom.
ENDMETHOD.
"constructor
METHOD get_uom.
r_uom = uom.
ENDMETHOD.
ENDCLASS.

"get_uom
"lcl_2d_shape IMPLEMENTATION

CLASS lcl_square DEFINITION INHERITING FROM lcl_2d_shape.


PUBLIC SECTION.
METHODS: constructor IMPORTING imc_uom TYPE char3
imc_side TYPE i,
get_side RETURNING value(r_side) TYPE i,
get_area REDEFINITION.
PRIVATE SECTION.
DATA: side TYPE i.
ENDCLASS.
"lcl_square DEFINITION
CLASS lcl_square IMPLEMENTATION.
METHOD constructor.
super->constructor( imc_uom = imc_uom ).
side = imc_side.
ENDMETHOD.
"constructor
METHOD get_side.
r_side = side.
ENDMETHOD.

"get_side

METHOD get_area.
r_area = side * side.
ENDMETHOD.
"get_area
ENDCLASS.
"lcl_square IMPLEMENTATION
CLASS lcl_circle DEFINITION INHERITING FROM lcl_2d_shape.
PUBLIC SECTION.
METHODS: constructor IMPORTING imc_uom TYPE char3
imc_rad TYPE i,
get_radius RETURNING value(r_rad) TYPE f,
get_area REDEFINITION.

PRIVATE SECTION.
DATA: rad TYPE i.
CONSTANTS: pi TYPE f VALUE '3.2857'.
ENDCLASS.
"lcl_circle DEFINITION
CLASS lcl_circle IMPLEMENTATION.
METHOD constructor.
super->constructor( imc_uom = imc_uom ).
rad = imc_rad.
ENDMETHOD.
"constructor
METHOD get_radius.
r_rad = rad.
ENDMETHOD.

"get_radius

METHOD get_area.
r_area = 2 * pi * rad.
ENDMETHOD.
"get_area
ENDCLASS.
"lcl_circle IMPLEMENTATION
***************************
START-OF-SELECTION.
DATA: shape2d TYPE REF TO lcl_2d_shape,
area TYPE f,
uom TYPE char3.
CREATE OBJECT shape2d TYPE lcl_circle EXPORTING imc_uom = 'cm'
imc_rad = 5.
area = shape2d->get_area( ).
uom = shape2d->get_uom( ).
WRITE: /3 'Area of circle:', area DECIMALS 4 EXPONENT 0, uom.
CREATE OBJECT shape2d TYPE lcl_square EXPORTING imc_uom = 'm'
imc_side = 6.
area = shape2d->get_area( ).
uom = shape2d->get_uom( ).
WRITE: /3 'Area of square:', area DECIMALS 4 EXPONENT 0, uom.

Exceptions & Exception Handling:


The term Exception refers to an abnormal situation that arises during a program execution where there is
no point in continuing to run the program in the normal way. The SAP Web AS 6.10 introduced a new
ABAP Objects exception concept, parallel to the exception concept in procedural programming.
Exceptions and exception handling are now based on classes.
A given abnormal situation is represented by a class. For example an attempt to divide a number by zero
is represented by the predefined class CX_SY_ZERODIVIDE. In the SAP standard system, the names of
all exception classes start with CX_.
An exception can only be handled if the statement that resulted in the exception to occur is enclosed in a
TRY-ENDTRY block. The exception is then handled using the CATCH statement in the TRY-ENDTRY
block.

1. REPORT SQUAREROOT.
2. PARAMETERS: NUM TYPE P.
3. DATA: RES TYPE P DECIMALS 2.
4. START-OF-SELECTION.
5. RES = SQRT( NUM ).
6. WRITE: / 'Square root of', NUM, 'is', RES.
While executing the above report program; if a negative value is entered in the selection screen, an
exception occurs as square root cannot be calculated for a negative value and the execution results in
abnormal termination of the program. To be precise it is the 5 th line of code RES = SQRT( NUM ) which
results in the abnormal condition. The standard SAP class that represents this abnormal condition is
CX_SY_ARG_OUT_OF_DOMAIN. The code below explains how to use a TRY-ENDTRY block and a
CATCH statement to avoid abnormal termination and an alternative way to process the input.
REPORT SQUAREROOT.
PARAMETERS: NUM TYPE P.
DATA: RES TYPE P DECIMALS 2.
START-OF-SELECTION.
TRY.
RES = SQRT( NUM ).
CATCH CX_SY_ARG_OUT_OF_DOMAIN.
WRITE: / 'Cannot calculate square-root for a negative value'.
WRITE: / 'The entered -ve value has been negated again to make it +ve'.
NUM = NUM * -1.
RES = SQRT( NUM ).
ENDTRY.
WRITE: / 'Square root of', NUM, 'is', RES.
Multiple CATCH statements within a single TRY-ENDTRY block:
A TRY-ENDTRY block can contain multiple CATCH statements, where each catch statement deals with a
different exception condition.
1. REPORT DIVISION_AND_SQUARE.
2. PARAMETERS: num TYPE p OBLIGATORY, numerator
i. den TYPE p OBLIGATORY. denominator
3. DATA: res TYPE p DECIMALS 2.
4. START-OF-SELECTION.
5. RES = NUM / DEN.
6. WRITE: /3 NUM, '/', DEN, '=', RES.
7. *& Multiplication may result in arithmetic overflow error if the computed
8. *& value is too large to be stored in packed-decimal type
9. RES = NUM * NUM.

10. WRITE: /3 'Square of', NUM, '=', RES.


In the above report program if a value zero is entered in the selection screen for denominator the
exception CX_SY_ZERODIVIDE is raised by the SAP system when the 5 th line of code is executed. On
the other hand, if a large value, say 8100000, is entered as the numerator an attempt to calculate the
square will result in value that is too large to be stored in a data object of packed decimal type; and in this
situation the system raises the exception CX_SY_ARITHMETIC_OVERFLOW.
REPORT DIVISION_AND_SQUARE.
PARAMETERS: num TYPE p OBLIGATORY DEFAULT 810000,
den TYPE p OBLIGATORY DEFAULT 9.
DATA: res TYPE p DECIMALS 2.
START-OF-SELECTION.
TRY.
*& Division may result in zero-divide error
res = num / den.
WRITE: /3 num, '/', den, '=', res.
SKIP 2.
*& Multiplication may result in arithmetic overflow error if the computed
*& value is too large to be stored in packed-decimal type
res = num * num.
WRITE: /3 'Square of', num, '=', res.
SKIP 2.
CATCH CX_SY_ARITHMETIC_OVERFLOW.
WRITE: /3 'Square of', num, 'too large.'.
CATCH CX_SY_ZERODIVIDE.
WRITE: /3 'You attempted to divide by ZERO.'.
ENDTRY.
WRITE: /3 'Report execution completed.'.
NOTE: When multiple CATCH statements are used in the same TRY-ENDTRY block, the CATCH
statement of a superclass exception should not precede the CATCH statement of a subclass exception.
An attempt to place the CATCH statement of a superclass exception before the subclass exception will
result in syntax error. This is because the superclass exceptions CATCH statement will end up catching
all its subclass exceptions too and hence the CATCH statement of the subclass exceptions will never be
reached.
The hierarchy of exception classes that are related to arithmetic operations is given below. The supermost class of exception classes in SAP is CX_ROOT.
CX_ROOT
CX_DYNAMIC_CHECK
CX_SY_ARITHMETIC_ERROR

CX_SY_ARG_OUT_OF_DOMAIN

CX_ARITHMETIC_OVERFLOW

CX_ZERODIVIDE

In the below code there are 3 possible exception (error) conditions:


1. If denominator is given as zero, CX_ZERODIVIDE will be raised by the SAP system.
2. If
the
numerator
is
a
negative
value,
for
calculation
of
square-root
CX_SY_ARG_OUT_OF_DOMAIN will be raised.
3. If the numerator value is too large, for calculation of square CX_ARITHMETIC_OVERFLOW will
be raised.
In the TRY-ENDTRY block two catch statements are provided, the first is for CX_ZERODIVIDE and the
second
for
CX_SY_ARITHMETIC_ERROR.
No
catch
statement
is
provided
for
CX_SY_ARG_OUT_OF_DOMAIN and CX_ARITHMETIC_OVERFLOW. But still, these two exceptions
will be caught by the second CATCH statement as CX_SY_ARITHMETIC_ERROR is superclass of the
exception classes that we are not handling.
PARAMETERS: num TYPE p OBLIGATORY DEFAULT 810000,
den TYPE p OBLIGATORY DEFAULT 9.
DATA: res TYPE p DECIMALS 2.
START-OF-SELECTION.
TRY.
*& Division may result in zero-divide error
res = num / den.
WRITE: /3 num, '/', den, '=', res.
SKIP 2.
*& Multiplication may result in arithmetic overflow error if the computed
*& value is too large to be stored in packed-decimal type
res = num * num.
WRITE: /3 'Square of', num, '=', res.
SKIP 2.
*& Calculating squareroot of a negative value results in out-of-domain error
res = SQRT( num ).
WRITE: /3 'Squareroot of', num, '=', res.
* CATCH CX_SY_ARITHMETIC_ERROR.
*
WRITE: /3 'An arithmetic error occured'.
CATCH cx_sy_zerodivide.
WRITE: /3 'You attempted to divide by ZERO.'.
CATCH cx_sy_arithmetic_error.
WRITE: /3 'An arithmetic error occured'.
ENDTRY.
WRITE: /3 'Report execution completed.'.
NOTE: In the above code the catch-statement of CX_SY_ARITHMETIC_ERROR cannot precede the
CATCH statement of CX_SY_ZERODIVIDE, as the CX_SY_ARITHMETIC_ERROR is a superclass of the
CX_SY_ZERODIVIDE. Any attempt to do so will result in syntax error, as the catch-statement of
CX_SY_ZERODIVIDE will be an unreachable code.