How can I represent a more "complex" constructor in ABAP? - abap

I have some Java code which i want to transfer into ABAP. I struggle with the attributes and constructor declaration/implementation.
How can I represent the folllowing Java code in ABAP?
class Node {
private String data;
private Node[] children = new Node[0];
private Node parent = null;
public Node(String data) {
this(data, null);
}
public Node(String data, Node child) {
this.data = data;
if (child != null) {
this.addChild(child);
}
}
}

This is as near as you can get:
CLASS node DEFINITION
PUBLIC CREATE PUBLIC.
PUBLIC SECTION.
METHODS constructor
IMPORTING
data TYPE string
child TYPE REF TO node OPTIONAL.
PRIVATE SECTION.
DATA data TYPE string.
DATA children TYPE STANDARD TABLE
OF REF TO node WITH EMPTY KEY.
DATA parent TYPE REF TO node.
ENDCLASS.
CLASS node IMPLEMENTATION.
METHOD constructor.
me->data = data.
IF child IS BOUND.
INSERT child INTO TABLE children.
ENDIF.
ENDMETHOD.
ENDCLASS.
ABAP doesn’t support overloading, meaning you cannot have multiple variants of a method with different sets of input parameters.

You Cant do "exactly" what you want. ABAP is not fully polymorphic like most OO languages.
You cant have 2 constructors with different signatures.
You can have a constructor with optional parameters and get a very similar result.
Have a go and see what you manage and post again.

Let me throw in another option, if you have multiple variants for construction and want to prevent optional parameters:
CLASS node DEFINITION
PUBLIC CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS create_with_data
IMPORTING
data TYPE string
RETURNING
VALUE(result) TYPE REF TO node.
CLASS-METHODS create_with_data_and_child
IMPORTING
data TYPE string
child TYPE REF TO node
RETURNING
VALUE(result) TYPE REF TO node.
PRIVATE SECTION.
DATA data TYPE string.
DATA children TYPE STANDARD TABLE
OF REF TO node WITH EMPTY KEY.
DATA parent TYPE REF TO node.
METHODS constructor
IMPORTING
data TYPE string
child TYPE REF TO node OPTIONAL.
ENDCLASS.
CLASS node IMPLEMENTATION.
METHOD create_with_data.
result = NEW #( data = data ).
ENDMETHOD.
METHOD create_with_data_and_child.
result = NEW #(
data = data
child = child ).
ENDMETHOD.
METHOD constructor.
me->data = data.
IF child IS BOUND.
INSERT child INTO TABLE children.
ENDIF.
ENDMETHOD.
ENDCLASS.

Related

ABAP throws "unknown type of class" error

I´m creating an ABAP program which uses 2 different classes. The first class is for selection data and presenting an ALV report. The second one is to extract that data to an CSV file.
When i am trying to call those methods in START-OF-SELECTION, i´m getting an error which says that " the type of "LCL_EXTRACTOR" is unknown".
I have the following code on my class definition:
CLASS lcl_extractor DEFINITION.
PUBLIC SECTION.
METHODS: write_data IMPORTING t_talv TYPE ty_t_talv.
METHODS constructor.
ENDCLASS.
On my start of selection I have:
START-OF-SELECTION.
CALL METHOD main=>inicializacao.
CALL METHOD lcl_extractor=>write_data( t_talv = t_talv ).
Can someone help me please to understand what I am doing wrong?
My classes are defined as:
CLASS main DEFINITION FINAL.
PUBLIC SECTION.
CLASS-METHODS inicializacao.
CLASS-METHODS principal.
ENDCLASS.
CLASS main IMPLEMENTATION.
METHOD inicializacao.
ENDMETHOD.
METHOD principal.
ENDMETHOD.
CLASS lcl_extractor DEFINITION.
PUBLIC SECTION.
METHODS: write_data IMPORTING t_talv TYPE ty_t_talv.
METHODS constructor.
ENDCLASS.
METHOD write_data.
ENDMETHOD.
ENDCLASS.
P.S: That t_talv table is the table which is presented on my ALV.
Thanks
You are calling method as static while it is defined as instance. Change the calling line to
NEW lcl_extractor( )->write_data( t_talv = t_talv ).
or make the method static.

method overriding for member variable

My understanding is that we can't override the member variable but when i am running the below program, i am getting unexpected o/p
class Parent {
String message = "parent";
void say() {
System.out.println(message);
}
}
class Child extends Parent {
String message = "child";
}
public class Test {
public static void main(String[] args) {
new Child().say();
}
}
In the o/p i am getting "parent" While we are calling the say method using child object and even there is no Parent reference.
Can anybody help me to understand it.
Thanks
The "say" method is on the parent class, not on the child. So when it call for the "message" member it looks at his own, not at the child's one. The fact that the call is make through a child class has nothing to do in it.
Indeed, the member variable is not overriden here. This is expected behavior.
EDIT :
The Java Language Specification says that "If the class declares a field with a certain name, then the declaration of that field is said to hide any and all accessible declarations of fields with the same name in superclasses, and superinterfaces of the class."
"Inherit" does not mean "copy". When you call the "say" method on a child instance, is not a "code copy" of the method that is called, but the method of the parent class, as it is defined in the parent class. And the parent class know nothing about the child variable member.
your child class is extend parent class features! so child class has say method by default and it's value (parent) because parent class say method will called when you call say method from child object. if you want to print "child" instead, you need override your say method in the child class and change that default feature, which extends from parent class.

OOP inheritance memory initialization

When you're instantiating an object of a class that inherits from a parent class the constructor calls the superclasses constructor in most langiages I know and my question is: when the superclasse's constructor is called there will effectively be an object of that type in memory, but we're creating an object of the subclass with(in this example) additional values to add to the object so how is that accomplished in memory? Is it added to the original object? Are the contents of the original object copied into a new object with space for all the variables? Or is it something completely different?
A different question that just occured to me, are class variables, like in java, kept in the data segment of the program in memory? How are classes, not the objects, stored in memory for that matter?
Thanks.
I don't really know how engine works, but I know how to test memory usage in PHP. Both scripts
class base {
public function __construct() {
}
}
$start_memory = memory_get_usage();
$object = new base;
echo memory_get_usage() - $start_memory;
and
class base {
public function __construct() {
}
}
class derived extends base {
public function __construct() {
}
}
$start_memory = memory_get_usage();
$object = new derived;
echo memory_get_usage() - $start_memory;
return the same value. It means there'is only one instance in memory, not parent + it's child, when class is extended
phpfiddles: 1st script, 2nd script
Classed are code that define its object, so they are in Code Segment of program. And all class variables are in data segment.
And when we create an object of subclass, first its parents' object are created and it is extended for subclass members. That's why subclass object has all members of its parent class.

How to access a public type of an object

I have a class named ZCL_RM_SPREADSHEETML.
It has in the Types tab a type called TY_STYLE with visibility 'Public' and it is defined with Direct Type Entry.
When I try to declare in the caller code the following :
DATA : wa_blue_style TYPE zcl_rm_spreadsheetml-ty_style.
I get the following:
The type "ZCL_RM_SPREADSHEETML" has no structure and therefore no
component called "TY_STYLE". .
This makes some sense I guess as ZCL_RM_SPREADSHEETML is a class, also double-clicking TY_STYLE does absolutely nothing.
Then I tried the following with a tilda:
DATA : wa_blue_style TYPE zcl_rm_spreadsheetml~ty_style.
I got the following:
Type "ZCL_RM_SPREADSHEETML~TY_STYLE" is unknown
Double clicking TY_STYLE will bring me though to the definition of TY_STYLE, so I must be close. The last time I had a similar issue it was because I was accessing a private method, but I marked the type clearly as Public.
Any ideas of what I am doing wrong?
EDIT
I also tried per the comment
DATA : wa_blue_style TYPE ref to zcl_rm_spreadsheetml->ty_style. "and
DATA : wa_blue_style TYPE zcl_rm_spreadsheetml->ty_style.
which gives
Field "ZCL_RM_SPREADSHEETML" is unknown. It is neither in one of the
specified tables nor defined by a "DATA" statement.
Which gave me the idea to try this the 'class' way,
DATA : wa_blue_style TYPE zcl_rm_spreadsheetml=>ty_style.
This works
You have to use the appropriate component selector:
Defined character that can be used to address components of upper units. There is a structure component selector (-), a class component selector (=>), an interface component selector (~), and an object component selector (->).
In this case, you're accessing a type (component) of a class, so you have to use =>.
You meant this, right?
report zstructsob.
*&---------------------------------------------------------------------*
*& Class MYCLASS
*&---------------------------------------------------------------------*
* Text
*----------------------------------------------------------------------*
class myclass definition.
public section.
types: begin of mystruct, " ------------> The public type
field1 type i,
field2 type string,
end of mystruct.
methods print_data importing data type mystruct.
private section.
data mydata type mystruct.
endclass. "MYCLASS
*&---------------------------------------------------------------------*
*& Class (Implementation) MYCLASS
*&---------------------------------------------------------------------*
* Text
*----------------------------------------------------------------------*
class myclass implementation.
method print_data.
write:/ data-field1, data-field2.
endmethod.
endclass. "MYCLASS
start-of-selection.
data ztype type myclass=>mystruct. " ------------> The public type of the class
data zclass type ref to myclass.
create object zclass.
ztype-field1 = 1.
ztype-field2 = 'Field2'.
zclass->print_data( ztype ).

Protobuf-net. Deserialize based on

Let's say we have the following three classes:
[ProtoContract]
[ProtoInclude(10, typeof(FirstType))]
[ProtoInclude(20, typeof(SecondType))]
public class Base
{
[ProtoMember(1)]
public int ClassId {get;set;}
}
public class FirstClass : Base
{
...
}
public class SecondClass : Base
{
...
}
And there's relationship between the class Id (in the base class) and the type of a matching child class. For example,
var obj1 = new FirstClass() {ClassId = 1}
var obj2 = new SecondClass() {ClassId = 2}
Now let's suppose we have serialized those objects. The question is: is there any good way to deserialize the serialized protobuf based the class Id value by looking over the ClassId field? i.e., if the value of classId in the serailized protobuf is 1, then use FirstClass to deserialize remaining stream bytes.
thanks!
If you are using ProtoInclude, then protobuf-net is already taking care of which subclass to use: that is the entire point of ProtoInclude. In some cases it is not possible to use inheritance, in which case there are ways to read the proto-stream via either ProtoReader, or by using a second model which only reads that property, then resetting the source and reading again. There is an example of that here: https://stackoverflow.com/a/14572685/23354