06-10-2013 9:27 AM
Hello, I'm trying to understand narrow & widening cast, for this reason I develop a simple class in order to understand correctly. Here is my source code:
REPORT ZBC_OBJECTS.
CLASS lcl_vehicle DEFINITION.
PUBLIC SECTION.
METHODS: constructor IMPORTING
im_max_speed TYPE i
im_number_of_wheels TYPE i.
PRIVATE SECTION.
DATA: max_speed TYPE i,
number_of_wheels TYPE i.
ENDCLASS.
CLASS lcl_vehicle IMPLEMENTATION.
METHOD constructor.
max_speed = im_max_speed.
number_of_wheels = im_number_of_wheels.
ENDMETHOD.
ENDCLASS.
CLASS lcl_truck DEFINITION INHERITING FROM lcl_vehicle.
PUBLIC SECTION.
METHODS: constructor IMPORTING
im_max_speed TYPE i
im_number_of_wheels TYPE i
im_load_capacity TYPE i.
PRIVATE SECTION.
DATA: load_capacity TYPE i.
ENDCLASS.
CLASS lcl_truck IMPLEMENTATION.
METHOD constructor.
super->constructor(
im_max_speed = im_max_speed
im_number_of_wheels = im_number_of_wheels ).
load_capacity = im_load_capacity.
ENDMETHOD.
ENDCLASS.
DATA: vehicle TYPE REF TO lcl_vehicle,
truck TYPE REF TO lcl_truck.
START-OF-SELECTION.
CREATE OBJECT vehicle EXPORTING
im_max_speed = 325
im_number_of_wheels = 4.
CREATE OBJECT truck EXPORTING
im_max_speed = 100
im_number_of_wheels = 8
im_load_capacity = 5000.
vehicle ?= truck. " Vehicle now have attribute +load_capacity (Widening cast)
the widening cast is working (I think), how can I "simulate" the narrowing cast in my own example. Thanks!
06-10-2013 10:07 AM
Hi Georgi,
Please let me give some references to casting examples:
http://scn.sap.com/message/13989885#13989885 - simple example with pizza
http://scn.sap.com/message/13857599#13857599 - example with vehicles
In your case if you want to see example of narrow casting then just modify your code by adding new variable lo_truck_vehicle_type:
DATA: lo_vehicle TYPE REF TO lcl_vehicle,
lo_truck TYPE REF TO lcl_truck,
lo_truck_vehicle_type TYPE REF TO lcl_vehicle.
START-OF-SELECTION.
CREATE OBJECT lo_vehicle EXPORTING
im_max_speed = 325
im_number_of_wheels = 4.
CREATE OBJECT lo_truck EXPORTING
im_max_speed = 100
im_number_of_wheels = 8
im_load_capacity = 5000.
lo_vehicle ?= lo_truck. " Vehicle now have attribute +load_capacity (Widening cast)
lo_truck_vehicle_type ?= lo_vehicle. " you can simply assign same type level
" In line below we are assigning basic type to extended type because we are sure that runtime
" object type is actually TRUCK even if variable type is VEHICLE
lo_truck ?= lo_truck_vehicle_type.
Of course code above is just for demonstration. In real life you may have method that has input parameter TYPE LCL_VEHICLE. Let say it is driver_over_bridge You cannot change method signature (maybe it is SAP standard and you want just to add implicit enhancement inside method). In case if you know that runtime instance of LCL_TRUCK is given, mail should be sent if truck is too heavy. But the weight/load_capacity is only attribute of truck, not the vehicle. So you can add implementation to the method:
TRY.
DATA lo_truck TYPE LCL_TRUCK.
lo_truck ?= lo_vehicle.
" no error - yes it is a truck instance
IF ( lo_truck->get_load_capacity( ) > 1000 ). " you have access to truck methods/atributes here if you need
send_email( "vehicle is truck type, may be too heavy" ).
ENDIF.
CATCH cx_root.
" it was not truck, do not make any action
ENDTRY.
Hope this helps.
Regards
Adam
06-10-2013 9:58 AM
Hello Goergi,
A widening cast should be if you create an instance like this:
create object vehicle type lcl_truck.
truck ?= vehicle.
Kind regards,
Hendrik
06-10-2013 10:15 AM
Exactly!
But we've a "Houston, we have a problem" situation here The constructor of the sub-class LCL_VEHICLE has a mandatory param load_capacity which would cause the problem.
So the OP needs to change the definition of the constructor to (which i think he should do) -
METHODS: constructor IMPORTING
im_max_speed TYPE i
im_number_of_wheels TYPE i
im_load_capacity TYPE i OPTIONAL. "-->Change this param to Optional
Otherwise he has to follow 's solution
Imho all the CONSTRUCTORs of an inheritance tree should have the same interface, what do you say?
BR,
Suhas
06-10-2013 11:08 AM
In my opinion constructor parameters should reflect what is really needed for object initialization, so I would not restrict to the rule of common interface. But if classes in inheritance tree requires same parameters for initialization, then it is ok. We must be aware when using optional parameters - not for syntax simplification but to reflect requirements that load_capacity may be skipped for truck in our case and truck can exists without this value.
On the other hand I do not like restriction in ABAP that only one constructor is allowed. That is why I prefer to create objects by factory methods (create_vehicle) with different parameters set unless I am really sure that object always needs same mandatory parameters for initialization - then constructor is desired.
Kind regards
Adam
06-10-2013 10:01 AM
Hi Georgi,
Refer to this link on narrow casting. This link has same example:
06-10-2013 10:06 AM
DATA: r_vehicle TYPE REF TO lcl_vehicle,
r_truck TYPE REF TO lcl_truck,
Here lcl_truck is inherting LCL_vehicle.
* Narrowing Cast
r_vehicle = r_truck.
* Use of the subclass instance in the superclass context
ret = r_vehicle->MethodOFSuperclass( ).
The assignment of a subclass instance to a reference variable of the type "reference to superclass" is described as a narrowing cast, because you are switching from a more detailed view to a one with less detail.
You can now access the subclass method(which is inherited from superclass) with the help of superclass reference.
06-10-2013 10:07 AM
Hi Georgi,
Please let me give some references to casting examples:
http://scn.sap.com/message/13989885#13989885 - simple example with pizza
http://scn.sap.com/message/13857599#13857599 - example with vehicles
In your case if you want to see example of narrow casting then just modify your code by adding new variable lo_truck_vehicle_type:
DATA: lo_vehicle TYPE REF TO lcl_vehicle,
lo_truck TYPE REF TO lcl_truck,
lo_truck_vehicle_type TYPE REF TO lcl_vehicle.
START-OF-SELECTION.
CREATE OBJECT lo_vehicle EXPORTING
im_max_speed = 325
im_number_of_wheels = 4.
CREATE OBJECT lo_truck EXPORTING
im_max_speed = 100
im_number_of_wheels = 8
im_load_capacity = 5000.
lo_vehicle ?= lo_truck. " Vehicle now have attribute +load_capacity (Widening cast)
lo_truck_vehicle_type ?= lo_vehicle. " you can simply assign same type level
" In line below we are assigning basic type to extended type because we are sure that runtime
" object type is actually TRUCK even if variable type is VEHICLE
lo_truck ?= lo_truck_vehicle_type.
Of course code above is just for demonstration. In real life you may have method that has input parameter TYPE LCL_VEHICLE. Let say it is driver_over_bridge You cannot change method signature (maybe it is SAP standard and you want just to add implicit enhancement inside method). In case if you know that runtime instance of LCL_TRUCK is given, mail should be sent if truck is too heavy. But the weight/load_capacity is only attribute of truck, not the vehicle. So you can add implementation to the method:
TRY.
DATA lo_truck TYPE LCL_TRUCK.
lo_truck ?= lo_vehicle.
" no error - yes it is a truck instance
IF ( lo_truck->get_load_capacity( ) > 1000 ). " you have access to truck methods/atributes here if you need
send_email( "vehicle is truck type, may be too heavy" ).
ENDIF.
CATCH cx_root.
" it was not truck, do not make any action
ENDTRY.
Hope this helps.
Regards
Adam