Application Development Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 

Dynamically accessing subclass attribute from within superclass method

Former Member
0 Kudos

Hello ABAP pros,

I'm trying to dynamically access attributes from within a superclass method. This works for all superclass attributes but not for the subclass attributes.

Imaging the following:

In an abstract superclass I define protected attributes a and b. In a subclass, inheriting from this superclass, I define a third protected attribute c. Now I'd like to define a method in the superclass which should dynamicall fill a structure out of all accessible instance attributes.

This method somehow looks like this:

METHOD to_structure.   DATA:     lref_structure_description TYPE REF TO cl_abap_structdescr,     lref_structure_object TYPE REF TO data,     lv_empty TYPE string.   FIELD-SYMBOLS:     <ls_component> TYPE abap_compdescr,     <lv_value> TYPE any,     <ls_structure> TYPE any,     <lv_structure_component_value> TYPE any.

  " get_structure_description( ) is a self written method that returns a RTTI description object of the desired structure of attributes   lref_structure_description = me->get_structure_description( ).   IF es_structure IS REQUESTED.     CREATE DATA lref_structure_object TYPE HANDLE lref_structure_description.     ASSIGN lref_structure_object->* TO <ls_structure>.     LOOP AT lref_structure_description->components ASSIGNING <ls_component>.       IF <lv_value> IS ASSIGNED.         UNASSIGN <lv_value>.       ENDIF.       ASSIGN me->(<ls_component>-name) TO <lv_value>.       IF <lv_value> IS NOT ASSIGNED.         ASSIGN lv_empty TO <lv_value>.       ENDIF.       IF <lv_structure_component_value> IS ASSIGNED.         UNASSIGN <lv_structure_component_value>.       ENDIF.       ASSIGN COMPONENT <ls_component>-name OF STRUCTURE <ls_structure> TO <lv_structure_component_value>.       IF <lv_structure_component_value> IS ASSIGNED.         <lv_structure_component_value> = <lv_value>.       ENDIF.     ENDLOOP.     es_structure = <ls_structure>.   ENDIF. ENDMETHOD.

The problem lies within the line "ASSIGN me->(<ls_component>-name) TO <lv_value>.". This works for <ls_component>-name = a and <ls_component>-name = b but not for <ls_component>-name = c (the subclass attribute).

I call the method on an instance of the subclass. The debugger shows that "me" is an instance of the subclass and if I enter "me->c" in the debugger I see the corresponding value. But <lv_value> just won't get assigned in this case. It also does not work if I specify the component name fully dynamic (test = 'me->' && <ls_component>-name. ASSIGN (test) TO <lv_value>.) nor if I explicitly use an object reference of the subclass (lref_subclass ?= me. ASSIGN lref_subclass->(<ls_component>-name) TO <lv_value>.).

It's a 7.31 SP3 system.

Any ideas what may be wrong here or is this just not possible?

1 ACCEPTED SOLUTION

Pawan_Kesari
Active Contributor
0 Kudos

Hi,

I can see where you are coming from. One would assume if value is being displayed in debug window then it can be assigned. Can't really explain what is wrong here but thing which I noticed is changing visibility of attribute C in subclass from protected to public all of sudden make it accessible though ASSIGN statement.

Regards,

Pawan.

9 REPLIES 9

UweFetzer_se38
Active Contributor
0 Kudos

Hi Christopher,

in my understanding of OO attributes and methods of subclasses are never visible in the superclass method.

0 Kudos

Hi Uwe,

that is what I was wondering about. If it wasn't possible, it would render dynamic programming quite useless in an OO context as you would have to redefine every method of the superclass that aims to work on subclass attributes.

Regards

Christopher

Pawan_Kesari
Active Contributor
0 Kudos

Hi,

I can see where you are coming from. One would assume if value is being displayed in debug window then it can be assigned. Can't really explain what is wrong here but thing which I noticed is changing visibility of attribute C in subclass from protected to public all of sudden make it accessible though ASSIGN statement.

Regards,

Pawan.

0 Kudos

Hi Pawan,

the visibility really seems to be the problem. I thought, if I call the method of the superclass on an object of the subclass, the visibility wouldn't matter. When I change the visibility of the subclass attribute to "public" or add the superclass as a friend to the subclass definition it works seamlessly. Thank you for the pointer!

I used the following two classes to test this:

class Z_CL_TEST_SUPER definition
  public
  abstract
  create public .

public section.

  methods CONSTRUCTOR
    importing
      !IV_A type STRING
      !IV_B type STRING .
  methods GET_C
    returning
      value(RV_VALUE) type STRING .
protected section.

  data ATTR_SUP_A type STRING .
  data ATTR_SUP_B type STRING .
private section.
ENDCLASS.


CLASS Z_CL_TEST_SUPER IMPLEMENTATION.

METHOD constructor.

  me->attr_sup_a = iv_a.
  me->attr_sup_b = iv_b.

ENDMETHOD.

METHOD get_c.

  DATA:
    lref_subclass TYPE REF TO z_cl_test_sub,
    lv_attribute_name TYPE string.

  FIELD-SYMBOLS:
    <lv_attribute_value> TYPE string.

  lv_attribute_name = 'attr_sub_c'.

  TRY.
      lref_subclass ?= me.
      ASSIGN me->(lv_attribute_name) TO <lv_attribute_value>.
      IF <lv_attribute_value> IS ASSIGNED.
        rv_value = <lv_attribute_value>.
      ENDIF.
    CATCH cx_root.
  ENDTRY.

ENDMETHOD.
ENDCLASS.

class Z_CL_TEST_SUB definition
  public
  inheriting from Z_CL_TEST_SUPER
  create public

  global friends Z_CL_TEST_SUPER .

public section.

  methods CONSTRUCTOR
    importing
      !IV_A type STRING
      !IV_B type STRING
      !IV_C type STRING .
protected section.

  data ATTR_SUB_C type STRING .
private section.
ENDCLASS.


CLASS Z_CL_TEST_SUB IMPLEMENTATION.

METHOD constructor.

  super->constructor(
    iv_a = iv_a
    iv_b = iv_b
  ).

  me->attr_sub_c = iv_c.

ENDMETHOD.
ENDCLASS.

DATA:
  lref_subclass TYPE REF TO z_cl_test_sub,
  lv_c TYPE string.

CREATE OBJECT lref_subclass
  EXPORTING
    iv_a = 'A'
    iv_b = 'B'
    iv_c = 'C'.

lv_c = lref_subclass->get_c( ).

When removing the friends statement, get_c won't return the value anymore.

Regards

Christopher

Message was edited by: Christopher Fenn

VijayaKrishnaG
Active Contributor
0 Kudos

Hi Christopher,

The Subclass attributes cannot be accessed in the Super class, why because the Subclass attributes are not visible to Super Class.

-Thanks,

Vijay

0 Kudos

If this is on purpose by SAP, this is kinda ridiculous. The super class is becoming part of the sub class, and the methods should behave exactly the same, with the same code.

This should work in either context, because me is of the same type, and should have the same visibility, no matter where it was declared:

ASSIGN me->(attr_name) TO <data>.

From my perspective this clearly is a bug in ABAP. But as always SAP is probably going to ignore this, or simply say it is on purpose, because [fill in excuse of the day].

Former Member
0 Kudos

I think you'll just have to override the superclass method in your subclass to do what you need it to do... You can still call the superclass method and add some extra logic after.

I also believe that a superclass having any knowledge of its subclasses is not really proper use of inheritance.

0 Kudos

Hello Lucas,

redefining the superclass method, implementing the subclass specific code in it and calling the superclass method afterwards, sounds like a great idea. Thank you for the hint!

My goal was to make the "framework" easily extensible by adding new subclasses to it. So I focused on implementing as much as possible in the abstract superclass (like persistency, serialisation, ...). The superclass methods are very generic through heavy usage of RTTI / RTTC classes. They have no special knowledge of the subclasses using it. The subclasses, on the other hand, have to follow some naming / visibility conventions to work as desired. The sample code I posted is greatly simplified to illustrate the problem I had.

Regards

Christopher

Former Member
0 Kudos

Hi,

I just stumbled upon this poroblem as well. ABAP Keyword Documentation states that this "may be used for all visible attributes of objects." Since attributes of a subclass are not visible to the superclass, it won't work.

Or should it?

I mean, the sublass inherits the method, making it its own method. At design time, it is pretty clear that this method belongs to the super class. At runtime, it belongs to the instance, which is an instance of the sub class. I guess one could argue whether visibility should be determined by where the method is implemented or by wht type of an instance the method belongs to at runtime.

My understanding would prefer the latter.