08-26-2009 4:32 PM
Hello All!
I am running into a problem of type compatibility when I declare a parameter of a subroutine as an abstract superclass and try to pass through a subclass. According to the documentation I have read, this should work (it also works in many other OOP languages). Furthermore, I attempted to create a field symbol of the superclass and assign the subclass to it, then pass it through to the subroutine, but the type incompatability error occurred there as well. This leads me to believe it is a problem with my declaration of the classes, but they seem alright. I am going to post example code in the following post.
Please examine and let me know if I am doing anything weird/wrong.
Thank you,
Steven Coolbaugh
08-26-2009 5:04 PM
You need to do the casting to the super's reference and use this object in the parameter of your Subroutine.
Like:
*----------------------------------------------------------------------*
* CLASS lcl_super DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_super DEFINITION ABSTRACT.
PROTECTED SECTION.
DATA: f_num1 TYPE i.
ENDCLASS. "lcl_super DEFINITION
*----------------------------------------------------------------------*
* CLASS lcl_sub DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_sub DEFINITION INHERITING FROM lcl_super.
PUBLIC SECTION.
METHODS:
set_f_num1
IMPORTING
if_num TYPE i,
get_f_num1
RETURNING
value(rf_num) TYPE i.
ENDCLASS. "lcl_sub DEFINITION
START-OF-SELECTION.
DATA: o_super TYPE REF TO lcl_super,
o_sub TYPE REF TO lcl_sub.
CREATE OBJECT o_sub.
o_sub->set_f_num1( 10 ).
o_super = o_sub. " Down Casting
PERFORM get_f_num USING o_super.
*&---------------------------------------------------------------------*
*& Form get_f_num
*&---------------------------------------------------------------------*
FORM get_f_num USING io_super TYPE REF TO lcl_super.
DATA: lo_sub TYPE REF TO lcl_sub,
lf_num TYPE i.
lo_sub ?= io_super. " Up Casting
lf_num = lo_sub->get_f_num1( ).
WRITE: lf_num.
ENDFORM. "get_f_num
*----------------------------------------------------------------------*
* CLASS lcl_sub IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_sub IMPLEMENTATION.
METHOD set_f_num1.
me->f_num1 = if_num.
ENDMETHOD. "set_F_num1
METHOD get_f_num1.
rf_num = me->f_num1.
ENDMETHOD. "get_f_num1
ENDCLASS. "lcl_sub IMPLEMENTATION
Regards,
Naimesh Patel
08-26-2009 5:04 PM
You need to do the casting to the super's reference and use this object in the parameter of your Subroutine.
Like:
*----------------------------------------------------------------------*
* CLASS lcl_super DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_super DEFINITION ABSTRACT.
PROTECTED SECTION.
DATA: f_num1 TYPE i.
ENDCLASS. "lcl_super DEFINITION
*----------------------------------------------------------------------*
* CLASS lcl_sub DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_sub DEFINITION INHERITING FROM lcl_super.
PUBLIC SECTION.
METHODS:
set_f_num1
IMPORTING
if_num TYPE i,
get_f_num1
RETURNING
value(rf_num) TYPE i.
ENDCLASS. "lcl_sub DEFINITION
START-OF-SELECTION.
DATA: o_super TYPE REF TO lcl_super,
o_sub TYPE REF TO lcl_sub.
CREATE OBJECT o_sub.
o_sub->set_f_num1( 10 ).
o_super = o_sub. " Down Casting
PERFORM get_f_num USING o_super.
*&---------------------------------------------------------------------*
*& Form get_f_num
*&---------------------------------------------------------------------*
FORM get_f_num USING io_super TYPE REF TO lcl_super.
DATA: lo_sub TYPE REF TO lcl_sub,
lf_num TYPE i.
lo_sub ?= io_super. " Up Casting
lf_num = lo_sub->get_f_num1( ).
WRITE: lf_num.
ENDFORM. "get_f_num
*----------------------------------------------------------------------*
* CLASS lcl_sub IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_sub IMPLEMENTATION.
METHOD set_f_num1.
me->f_num1 = if_num.
ENDMETHOD. "set_F_num1
METHOD get_f_num1.
rf_num = me->f_num1.
ENDMETHOD. "get_f_num1
ENDCLASS. "lcl_sub IMPLEMENTATION
Regards,
Naimesh Patel
08-26-2009 5:17 PM
Naimesh,
Thank you very much. I removed the ABSTRACT verbage from the Superclass Definition and the Method Declaration, then cast the subclass to a superclass reference before the call and it worked.
The vast majority of my experience is in VC++ and VB, so I was used to declaring formal parameters as superclasses and just sending subclasses through.
On a side note, I would like to thank you for your posts I have found online (Both on and off this site). It seems like whenever I have a question/problem, google comes back with a post by you that has a very thorough explanation of my question/problem. Thank you and keep up the good work!
Steven Coolbaugh
08-26-2009 5:17 PM
Naimesh,
Thank you very much. I removed the ABSTRACT verbage from the Superclass Definition and the Method Declaration, then cast the subclass to a superclass reference before the call and it worked.
The vast majority of my experience is in VC++ and VB, so I was used to declaring formal parameters as superclasses and just sending subclasses through.
On a side note, I would like to thank you for your posts I have found online (Both on and off this site). It seems like whenever I have a question/problem, google comes back with a post by you that has a very thorough explanation of my question/problem. Thank you and keep up the good work!
Steven Coolbaugh
08-26-2009 5:33 PM
Thanks for your compliments..!
You don't need to remove the ABSTRACT from the SUPER Class definition. ABSTRACT will only stop if you try to create an instance of that class. But if you have an instance created (of a subclass) and you are assigning that instance to the Object Reference which is declared with reference to the Abstract Super Class, it wont stop you.
Regards,
Naimesh Patel
08-26-2009 6:37 PM
Ah, once again my previous experience is causing problems. In C++, declarations of pointers to an object have a different declaration from object variable declarations. I keep forgetting that ABAP uses reference variables exclusively, therefore the object is not instanced (although had I thought about it, CREATE OBJECT would not need to be used if it worked otherwise). Thank you for the correction.
On a different note, I did not have to up cast the passed super object to the sub object; which is very good, since I am passing many different subclasses through to this subroutine.
Once again, thank you for your help.