Do you really know everything about typing? – part 4

When talking about typing there is also a topic which requires some attention, namely interface parameter typing. The interface here refers to procedure’s signature. From developers point of view this is like creating an API and exposing it to world. In other languages like C or VB, we usually see only this procedure interface as an entry point to some functional code behind it. This code can be hashed so it might not be seen by developer. We must therefore ensure that parameters we are passing are correctly typed.

Glossary

Before we start talking a little bit about the parameters themselves, I want you to get familiarized with the correct naming. In ABAP world, the procedure is code of block which has a signature (or interface), bodyand is reusable. So the procedure can be a Function Module, a Subroutineor a Method. The signature is nothing but how the procedure is seen outside (how it is exposed to the world). The body can be hidden (hashed) and is the actual code executed by procedure. I this blog I will be using name procedure when referring to any of the above. If referring to any specific I will directly point that out.

Local and global typing

In general you can use only global types (DDIC ones) for Function Modules’ and Methods’ parameters, and either local or global ones for Subroutines’. This however can be overcome, but is off-topic here.

Genericity

This term you might be already familiar with, or at least you have heard of that. Generic is something that is specified partly or is not specified at all. In ABAP it especially applies to typing parameters and field symbols. Saying that parameter is of generic type, means that developer (who uses the procedure) knows a little or knows nothing about the type of the parameter that should be passed. This implies that he/she can pass “partly any” or any data object he/she wants.

Let’s have a look at the below table of how SAP categorizes parameter typing:

Category

Generic formal data type

Possible actual data type

Fully generic

ANY

Any data type

Table-like

ANY TABLE

Any table data type

Index-accessed table

INDEX TABLE

STANDARD/SORTED table data type

Standard table

STANDARD TABLE, TABLE

Any standard table data type

Sorted table

SORTED TABLE

Any sorted table data type

Hashed table

HASHED TABLE

Any hashed table data type

Structure-like

STRUCTURE

Any DDIC structure data type (obsolete)

Elementary, flat

c, n, x, p

Data type of respective elementary type without length specification

As you can see parameter of type ANY really accepts data object of ANY data type. The similar is with type ANY TABLE.

Shopping relevance

You may think I am crazy but I think the generic typing has much more to do with shopping then we would think. Imagine that a wife (apologies to Ladies and bachelors) sends you to do the shopping in a supermarket. You get the following list of items:

0,5 kg Apples

Potatoes

One can of spinach

5 tomatoes

Some snacks

Milk

Beer

Such list would make me a little bit confused. While it is very clear to me that under beer she most probably meant six-pack 😉 I am desperately trying to figure out what she meant by Potatoes or Some snack. I am not quite sure whether we need 1kg or 2kg of the former, and which snack she feels like having. Basically we can categorize above lists into several groups:

I am sure what to buy

I am not quite sure – I will be guessing or I will call her

I have no clue what she meant

0,5 kg Apples,

5 tomatoes,

One can of spinach

Milk (1 or 2 cartons, how much fat),

Beer (actually she might want some for her)

Some snack (I probably buy any)

The things “I am sure about” in ABAP would map to fully specified. The things “I am not quite sure” in ABAP would be those semi specified (or semi generic). The ones “I have no clue about” are those fully generic.

Responsibility

While for shopping list I am taking full responsibility for not being smart enough to figure out what my wife has meant, in ABAP the original developer is the one who must assure data correctness (as different developers under “any” might understand something different).

If we create i.e. Function Module with parameter ANY TABLE we must ensure we are not trying to use it in any type specific operation i.e. the following would cause syntax error:

READ TABLE itab ... INDEX i_index.

Obviously we are trying to access the table via INDEX, but the table can be either STANDARD, SORTED or HASHED one. The last one can only be accessed by key. So although the above seems syntactically correct we would get the error as the system is not sure which kind of table we really mean. In order we could run the program we must change the parameter to typed as INDEX TABLE. This way we restrict “consumer” (developer) to pass only STANDARD or SORTED table, thereby making our function less generic (more specified).

Possibilities

The rule is simple, the more generic program is, the more useful it may become. However always you should not overuse this programming “feature”. At first place try to provide fully specified type, then if really necessary go for more generic typing.

Example

Let’s say we have the developed a generic READ function, which returns the record of any internal table we pass to the function either via index or key access. This function could look like

For importing parameters we used a fully specified i_key_fieldand i_index, a semi specified table (index table) and fully generic i_key_value(as we can pass any data object here) and es_line(return any structure line we want).

Formal vs actual parameter

Formal parameter is the one which a procedure has in its signature (interface), while the actualis the one passed to the procedure during its call. Therefore the formal parameter data type is the one which the parameter is typed with, while the actual has the type of real passed data object. During procedure call the formal parameter receives the actual one’s type.

Formal parameter data type must thereforealways be at least as “wide” as the actual parameter (or wider – more generic), but never vice versa. It must be possible to system to perform casting during parameter passing.

Note!

This restriction is especially important when passing object references, where casting to parent object is always possible, but to child object not necessarily. This is also a subject for dynamiccasting operator ?= . Don’t worry, we won’t go as deep in our considerations here. This might be a topic for some next blogs.

No static component

Another point to consider is that by making es_linegeneric, we can’t access its components in the function directly, like

es_line-carrid = … es_line-connid = …

This is simply because we don’t statically know whether this work area will ever receive the line type which has CARRID or CONNID components. This is only known during runtime – dynamically. So we say, the statictype of work area es_line (type of formal parameter) is generic but the dynamic one (type of actual parameter passed to procedure) will be as line of the table passed to FM.

Therefore in order we could access any of its components, we need to do this dynamically. This is the point where field symbols come into play.

Note!

Typing and working with field symbols is a task for next classes so I won’t be discussing it here now.

This small piece of code is quite powerful and we could it is such program

Of course the choice depends on different factors i.e. whether we want to use the procedure only for purpose of certain program. Usually there is no need to create highly generic routines just for usage of one program, but on the other hand there is sometimes no point in creating a function module just for one time and case use. So you should always try to balance this thing.

Anyhow the choice should be always made by asking yourself a question in this regard keeping in mind the order of typing to consider.

One more way for generic typing

Before we sum up I want you to be aware of one more thing. You can pass the parameter generically by means of its data reference(pointer). Please do not confuse it with passing by reference (the other way is passing by value).

The genericdata reference is of type

type ref to data

The same we have for objects (those typed as ref to class)

type ref to object

This means we can pass reference of any data object we want and later in the procedure body we can dereference it using field symbols (also casting here is possible). More on this will come in the next part of this blog series.

Note!

Such formal parameter should be treated with special care as actual parameter can pass any reference. So it is like using generic type ANY, but it simply comes in form of a pointer to any data object, rather as data object itself.

Conclusion

Although generic parameter typing is tempting, as you can work with partly any or entirely any data object you want, it is also very error prone. You should always try to type the parameter as much specified as it is possible and use more generic types only if the first fails. Well, the true is that this creates opportunities to developer, but also leaves all the responsibility for any inconsistencies in the procedure coming through the generic nature of the formal parameters.

Generic typing is also very useful in combination with field symbols. But this is a subject for next reading…