Classes in ABAP Objects are declared using the CLASS statement block. This statement block is a wrapper of sorts, grouping all relevant class component declarations into two distinct sections.
In this post, we’ll unpack the syntax used to build out these sections and fully specify class types. For the purposes of this introductory section, our focus will be on defining local classes (i.e., classes that are defined within ABAP report programs and function group includes).
It’s good to note that this same syntax applies to the definition of global class types as well. The primary difference in the caseof global classes is that you have a form-based editor in the Class Builder tool that spares you from manually typing out some of the declaration syntax.
To define a new class type, you must declare it within a CLASS...DEFINITION...ENDCLASS statement block as shown in the listing below. This statement block makes up the aforementioned declaration section of the ABAP class definition. This section is used to declare the primary components that make up a class, such as attributes and methods.
CLASS {class_name} DEFINITION [class_options].
PUBLIC SECTION.
[components]
PROTECTED SECTION.
[components]
PRIVATE SECTION.
[components]
ENDCLASS.
If you look closely, you can see that the components of a class definition are organized into three distinct visibility sections: the PUBLIC SECTION, the PROTECTED SECTION, and the PRIVATE SECTION. Each of these visibility sections is optional, so it’s up to you as a developer to determine which components go where.
Besides the definition of the components that makeup the class’s interface, the next most important task in defining a class is coming up with a good and meaningful name for it. As trivial as it may sound, this task is often harder than it looks. Part of the challenge stems from the fact that ABAP only gives you 30 characters to work with. You must come up with a meaningful name that fits within the confines of the syntax shown here.
[{Namespace}|{Prefix}]CL_{Meaningful_Name}
The following listing shows how this class naming syntax is applied to the various class types that may exist within the ABAP Repository.
LCL_LOCAL_CLASS "Local Customer Class
ZCL_GLOBAL_CLASS "Global Customer Class
CL_ABAP_MATCHER "SAP-Standard Class (no namespace)
/BOWDK/CL_STRING_UTILS "3rd-Party Class w/Namespace Prefix
As you’ve seen, the structure and makeup of a class is determined by its component definitions. Therefore, in this section, you’ll learn about the different component types that you can define within a class. Before you get started, though, you first need to understand how components are grouped from a scoping perspective. Within a class declaration, there are two different types of components.
Instance components, as the name suggests, are components that define the state and behavior of individual object instances. For example, an Employee class might have an instance attribute called id that uniquely identifies an employee within a company. Each instance of the Employee class maintains its own copy of the id attribute, which has a distinct value. Instance methods operate on these instance attributes to manipulate the object’s state and perform instance-specific tasks.
Class components, on the other hand, are defined at the class level, meaning class components are shared across all object instances. Such components can come in handy in situations where you want to share data or expose utility functions on a wider scale. For example, in the Employee class scenario, you might use a class attribute called next_id to keep track of the next available employee ID number. This value could be used as a primitive number range object to assign the id instance attribute for newly created Employee objects.
In practice, most of the classes you define will contain few class components. After all, it’s hard to establish identity at the object level if all the data and/or functionality resides in global class components. However, you’ll see that class components come in handy in certain situations, such as dealing with complex object creation scenarios or finding a home for utility functions.
Class components are sometimes referred to as static components since they are statically defined and maintained at the class level. This is especially the case in other object-oriented languages such as Java or C#.
Regardless of where you decide to define your components, it’s important to keep in mind that all component names within an ABAP Objects class belong to the same internal namespace. For example, it’s not possible to define an attribute and a method using the same name—even if they belong to different visibility sections. In the sections that follow, you’ll learn that the adoption of good naming conventions makes it easy to avoid such naming collisions.
Attributes are essentially variables defined internally within a class or object. Attributes are defined in the same way that variables are defined in other ABAP programming modules. The primary difference in the case of classes is that you’re contending with different contexts.
To put these contexts into perspective, consider the LCL_CUSTOMER sample class in the next listing. Within this class definition, we’ve defined three different types of attributes:
CLASS lcl_customer DEFINITION.
PUBLIC SECTION.
CONSTANTS: CO_PERSON_TYPE TYPE c VALUE '1',
CO_ORG_TYPE TYPE c VALUE '2',
CO_GROUP_TYPE TYPE c VALUE '3'.
PRIVATE SECTION.
DATA: mv_id TYPE i,
mv_customer_type TYPE c,
mv_name TYPE string,
ms_address TYPE adrc.
CLASS-DATA: sv_next_id TYPE i.
ENDCLASS.
Though the ABAP compiler will generally allow you to define attributes with whatever name you prefer, we strongly recommend that you adopt a naming convention that makes it easier to identify the scope of a given attribute.
Methods are defined using either the METHODS statement for instance methods or the CLASS-METHODS statement for class methods. The syntax for both statement types is shown in the syntax diagram below. Here, you can see that a method definition consists of a method name, an optional parameter list, and an optional set of exceptions that might occur. For this introductory section, we’ll focus on the first two parts of a method definition.
{CLASS-}METHODS {method_name}
[IMPORTING parameters]
[EXPORTING parameters]
[CHANGING parameters]
[RETURNING VALUE(parameter)]
[{RAISING}|{EXCEPTIONS}...].
As you can see, the first thing you specify in a method definition is the method’s name. Since methods define the behavior of classes, it’s important that you come up with meaningful names that intuitively describe the method’s purpose. Normally, it makes sense to prefix a method name with a strong action verb that describes the type of operation being performed. The sample class in this listing provides some examples of this convention.
CLASS lcl_date DEFINITION.
PUBLIC SECTION.
METHODS:
add IMPORTING iv_days TYPE i,
subtract IMPORTING iv_days TYPE i,
get_day_of_week RETURNING VALUE(rv_day) TYPE string,
...
ENDCLASS.
After you come up with meaningful names for your methods, your next objective is to determine what sort of parameters (if any) the methods will need to perform their tasks. If you look at the syntax diagram from earlier, you can see that there are four different types of parameters that can be defined within a method’s parameter list. This table describes each of these parameter types in detail.
| Parameter Type | Description |
| Importing | Importing parameters define the input parameters for a method. The values of an importing parameter cannot be modified inside the method implementation. |
| Exporting | Exporting parameters are input/output parameters that allow you to update or modify data within a method. |
| Changing | Changing parameters are input/output parameters that allow you to update or modify data within a method. |
| Returning | Returning parameters are used to define functional methods. |
To distinguish between the various parameter types within a method definition, method parameters are normally prefixed according to the convention described in the following table. Here, the {Type} designator is once again used to differentiate between elementary data types (V), structure types (S), table types (T), and so on.
| Parameter Type | Naming Convention |
| Importing | I{Type}_{Parameter_Name} |
| Exporting | E{Type}_{Parameter_Name} |
| Changing | C{Type}_{Parameter_Name} |
| Returning | R{Type}_{Parameter_Name} |
Regardless of the parameter’s type, the syntax for declaring a parameter p1 is shown in the syntax diagram in the next listing. As you can see, this syntax provides you with several configuration options for defining a parameter:
{ p1 | VALUE(p1)} TYPE type [OPTIONAL | {DEFAULT def1}]
At runtime, whenever a method that contains parameters is invoked, the calling program will pass parameters by matching up actual parameters (e.g., local variables in the calling program and literal values) in the method call with the formal parameters declared in the method signature. Here, parameters are passed in one of two ways: by reference (default behavior) or by value.
Pass-by-value semantics is enabled via the aforementioned VALUE addition. Performance- wise, pass-by-value implies that a copy of an actual parameter is created and passed to the method for consumption. As a result, changes made to value parameters inside the method only affect the copy; the contents of the variable used as the actual parameter are not disturbed in any way. This behavior is illustrated at the top of the figure below with the mapping of parameter a. Here, whenever the method is invoked, a copy of variable x is made and assigned to parameter a. As you might expect, this kind of operation can become rather expensive when you start dealing with large data objects.
Reference parameters, on the other hand, contain a reference (or pointer) to the actual parameter used in the method call. Therefore, changes made to reference parameters are reflected in the calling program. In our figure, this is illustrated in the mapping of parameter b. Here, if you were to change the value of parameter b inside the method, the change would be reflected in variable y in the calling program.
Since this behavior can potentially cause dangerous side effects, ABAP allows you to lock down reference parameters for editing inside methods by defining them as importing parameters. For example, if you define parameter b as an importing parameter, the compiler would complain if you try to modify its contents within the method body. In effect, importing parameters allow you to attain all the performance benefits of reference passing without the negative effects.
Collectively, a method’s name and parameter list make up the method’s signature. From the perspective of class consumers, method signatures determine the exact requirements for calling a particular method: which parameters to pass, the data types of the parameters being exchanged, and so on. As a method designer, it’s important that you get these details right so that your methods are intuitive and easy to use. To that end, here are some design points to consider when defining method signatures:
Besides the more common attributes and methods that you see in most object-oriented languages, ABAP Objects also allows you to define events that model certain types of occurrences within an object’s lifecycle. Once again, you can distinguish between instance events that occur within a specific object instance and class events that are defined at the class level.
The next listing contains the basic syntax used to define instance events and class events. The parameters defined for an event are used to pass additional information about the event to interested event handler methods. Since this is a one-way data exchange, you’re only allowed to define exporting parameters in an event definition. The syntax is pretty much identical to the syntax used to define exporting parameters in methods. The only difference in this case is that event parameters must be passed by value. Aside from the formally defined exporting parameters in an event definition, the system also supplies an implicit parameter called sender that contains a reference to the sending object (i.e., the object that raised the event).
EVENTS evt [EXPORTING parameters].
CLASS-EVENTS evt [EXPORTING parameters].
You can define custom data types within a class using the ABAP TYPES statement. These types are defined at the class level and are therefore not specific to any object instance. You can use these custom types to define local variables within methods, method parameter types, and so on. It’s also possible to declare the use of global type pools defined within the ABAP Dictionary using the TYPE-POOLS statement.
The definition of class LCL_PERSON in the next listing demonstrates how types can be declared and used in a class definition. Here, we’ve defined a custom structure type called TY_NAME that’s being used to define the person’s ms_name attribute. The use of the TY_ prefix in this case is by convention: Class-defined types are normally defined using the naming convention TY_{Type_Name}.
CLASS lcl_person DEFINITION.
PRIVATE SECTION.
TYPES: BEGIN OF ty_name,
first_name TYPE char40,
middle_initial TYPE char1,
last_name TYPE char40,
END OF ty_name.
TYPE-POOLS: szadr. "Business Address Services
DATA: ms_name TYPE ty_name,
ms_address TYPE szadr_addr1_complete.
ENDCLASS.
If you look closely, you can also see how type groups from the ABAP Dictionary are declared using the TYPE-POOLS statement. In this case, the class has declared the use of the SZADR type group from the Business Address Services package. Once this declaration is in place, you can use types such as the SZADR_ADDR1_COMPLETE type in attribute definitions and method signatures.
Any time you define methods within the declaration section of a class, you need to provide implementations for them in the implementation section. Such implementations are provided using METHOD...ENDMETHOD statement blocks that are nested inside of a CLASS...IMPLEMENTATION...ENDCLASS statement block, as shown here.
CLASS lcl_date DEFINITION.
...
ENDCLASS.
CLASS lcl_date IMPLEMENTATION.
METHOD add.
mv_date = mv_date + iv_days.
ENDMETHOD.
METHOD subtract.
mv_date = mv_date - iv_days.
ENDMETHOD.
METHOD get_day_of_week.
"Implementation goes here..
ENDMETHOD.
ENDCLASS.
As you can see, method implementations allow you to jump right into the code. There’s no need to provide any further details about the method context, since you’ve already defined its signature in the declaration section. Within the method processing block, you can implement the behavior of the class using regular ABAP statements in much the same way that you would implement subroutines and function modules from the procedural world.
If you’re coming to ABAP Objects from a procedural background, we should point out that there are a handful of ABAP language constructs that have been rendered obsolete/deprecated from within the object-oriented context. These changes came about as part of a language cleanup effort when SAP first introduced object-oriented extensions to ABAP. SAP saw an opportunity to do some internal housekeeping and ensure that deprecated language elements didn’t make their way into new ABAP Objects classes.
For the most part, developers following current best practices shouldn’t encounter these statements, as their use is generally frowned upon in any context. Still, if you’re not sure which statements have become deprecated over the years, don’t worry; the compiler will tell you if you’ve used one.
Before we wrap up our discussion on method implementations, let’s take a moment to discuss variable scoping rules in an object-oriented context. Unlike procedural contexts, where the context is pretty cut-and-dry between global variables and local variables, method implementations get their hands on variables at several different scoping levels:
With these additional options in play, you should be careful when qualifying variables so that their usage is clear. This makes the code more readable and prevents you from accidentally hiding instance or class attributes behind method-local variables with the same name. As you can expect, hiding instance or class attributes within a method can have some nasty side effects. Fortunately, if you stick to the naming conventions outlined, this shouldn’t ever be a concern.
Ready to level up your ABAP skills? Explore the full range of our ABAP-focused online courses, from foundational programming to advanced RAP, CDS, AMDP, unit testing, and more. Each one is instructor-led (live and on-demand), includes recordings and slide decks, and is designed to give you practical take-away skills you can apply right away in your SAP landscape. Click on the banner below to get started!
Understanding how classes are defined and used in ABAP Objects is foundational to writing clean, maintainable, and modern SAP applications. From the declaration and implementation sections to visibility levels, attributes, methods, parameter passing, events, and custom types, these building blocks give you the control and flexibility to model real-world business objects in a way that is intuitive and reusable across your SAP development projects.
Whether you're working with local classes inside an ABAP report program or building global class types in the Class Builder, mastering these fundamentals, along with best practices like consistent naming conventions, focused methods, and thoughtful visibility design, sets a strong foundation for exploring more advanced ABAP Objects concepts like inheritance, interfaces, and polymorphism.
Editor’s note: This post has been adapted from sections of the books Object-Oriented Programming with ABAP Objects by Jeffrey Boggess, Colby Hemond, James Wood, and Joseph Rupert. Jeffrey is an enterprise integration specialist at Bowdark Consulting focused on building seamless integrations between SAP, Azure, and Dataverse to solve complex business challenges and provide dependable solutions for clients. Colby is a senior technical consultant at Bowdark Consulting, where he is dedicated to bringing innovative ideas and solutions to clients and supporting them in their digital transformation. James is the founder and CEO of Bowdark Consulting, Inc., a consulting firm specializing in technology and custom development in the SAP landscape. Joseph is a senior data architect at Bowdark Consulting, Inc. with expertise in migrating complex SAP landscapes to cloud platforms, enabling scalable, secure, and high-performance data ecosystems.
This post was originally published 3/2026.