Can define variables as references to local classes defined in another program? - oop

I have a program ZPROG1_TEST where I define a local class LCL_PROG1_HELPER.
I have a second program ZPROG2_TEST where I'd like to define a variable reference to this class.
Isn't there a syntactic possibility for me to do this?
Or could this be in theory doable with the RTTI classes like CL_ABAP_CLASSDESCR ?
EXTRA
Why I'd like to do this is because I have a custom form ZMM_MEDRUCK that needs to know if the ME32N Document it's printing has been changed but not saved.
I've figures out the exact objects whose properties I need to interogate, but some of them are defined at design time as common interfaces, like IF_SERIALIZABLE_MM, and I need to cast them to the local classes whose instances I know these objects are going to be, like \FUNCTION-POOL=MEGUI\CLASS=LCL_APPLICATION.
I could of course try a dynamic method call and not care about anything, but since i'm here i thought i'd ask this thing first.

You could do it like that.
REPORT ZPROG1_TEST.
INTERFACE lif_prog1_helper.
METHODS:
test.
ENDINTERFACE.
CLASS LCL_PROG1_HELPER DEFINITION.
PUBLIC SECTION.
INTERFACES:
lif_prog1_helper.
ALIASES:
test FOR lif_prog1_helper~test.
ENDCLASS.
CLASS LCL_PROG1_HELPER IMPLEMENTATION.
METHOD test.
WRITE / sy-repid.
ENDMETHOD.
ENDCLASS.
REPORT ZPROG2_TEST.
DATA: g_test TYPE REF TO object.
START-OF-SELECTION.
CREATE OBJECT g_test TYPE ('\PROGRAM=ZPROG1_TEST\CLASS=LCL_PROG1_HELPER').
CALL METHOD g_test->('TEST').
CALL METHOD g_test->('LIF_PROG1_HELPER~TEST').

As far as I know, this is not possible. Accessing the local class dynamically is easy (well, relatively easy), but referring to it statically - not as far as I know. You'll probably have to call the methods dynamically.

Related

Resolving the method of a ABAP dynamic call: order of types considered

I try to provoke a behaviour described in the ABAP Keyword Documentation 7.50 but fail. It's given with Alternative 2 of CALL METHOD - dynamic_meth:
CALL METHOD oref->(meth_name) ...
Effect
... oref can be any class reference variable ... that points to an object that contains the method ... specified in meth_name. This method is searched for first in the static type, then in the dynamic type of oref
I use the test code as given below. The static type of oref is CL1, the dynamic type CL2. Shouldn't then the dynamic CALL METHOD statement call the method M in CL1?
REPORT ZU_DEV_2658_DYNAMIC.
CLASS CL1 DEFINITION.
PUBLIC SECTION.
METHODS M.
ENDCLASS.
CLASS CL1 IMPLEMENTATION.
METHOD M.
write / 'original'.
ENDMETHOD.
ENDCLASS.
CLASS CL2 DEFINITION INHERITING FROM CL1.
PUBLIC SECTION.
METHODS M REDEFINITION.
ENDCLASS.
CLASS CL2 IMPLEMENTATION.
METHOD M.
write / 'redefinition'.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
DATA oref TYPE REF TO cl1. " static type is CL1
CREATE OBJECT oref TYPE cl2. " dynamic type is CL2
oref->m( ). " writes 'redefinition' - that's ok
CALL METHOD oref->('M'). " writes 'redefinition' - shouldn't that be 'original'?
Update:
I'd like to answer to the (first four) comments to my original question. Because of the lengthy code snippet, I answer by augmenting my post, not by comment.
It is true that the behaviour of the code snippet of the original question is standard OO behaviour. It's also true that for calls with static method name and class, types are resolved as given by the link. But then:
Why does the ABAP Keyword Documentation make the statement I've linked?
Calls with dynamic method names do search for the method name in the dynamic type, as demonstrated by the following code piece. That's certainly not standard OO behaviour.
My question was: Apparently, the search mechanism differs from the one described. Is the description wrong or else do I miss something?
REPORT ZU_DEV_2658_DYNAMIC4.
CLASS CL_A DEFINITION.
ENDCLASS.
CLASS CL_B DEFINITION INHERITING FROM CL_A.
PUBLIC SECTION.
METHODS M2 IMPORTING VALUE(caller) TYPE c OPTIONAL PREFERRED PARAMETER caller.
ENDCLASS.
CLASS CL_B IMPLEMENTATION.
METHOD M2.
write / caller && ' calls b m2'.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
DATA orefaa TYPE REF TO cl_a.
CREATE OBJECT orefaa TYPE cl_a. " static and dynamic type is CL_A
*orefaa->m2( 'orefa->m2( )' ). syntax error: method m2 is unknown'.
*CALL METHOD orefaa->('M2') EXPORTING caller = 'CALL METHOD orefa->("M2")'. results in exception: method m2 is unknown'.
DATA orefab TYPE REF TO cl_a. " static type is CL_A
CREATE OBJECT orefab TYPE cl_b. " dynamic type is CL_B
*orefab->m2( 'orefab->m2( )' ). results in syntax error: method m2 is unknown'.
CALL METHOD orefab->('M2') EXPORTING caller = 'CALL METHOD orefab->("M2")'. " succeeds
You are actually answering your own question there, aren't you?
In your first example, you perform a call method to the method m on a variable that's typed as cl1. The runtime looks up the class cl1, and finds the requested method m there. It then calls that method. However, your variable actually has the type cl2, a sub-class of cl1, that overrides that method m. So the call effectively reaches that redefinition of the method, not the super-class's original implementation. As you and the commenters sum it up: this is standard object-oriented behavior.
Note how in essence this has nothing to do at all with the static-vs-dynamic statement you quote from the documentation. The method m is statically present in cl1, so there is no dynamic lookup involved whatsoever. I assume you were looking for a way to probe the meaning of this statement, but this example doesn't address it.
However, your second example then precisely hits the nail on the head. Let me rewrite it again with different names to talk it through. Given an empty super class super_class:
CLASS super_class DEFINITION.
ENDCLASS.
and a sub-class sub_class that inherits it:
CLASS sub_class DEFINITION
INHERITING FROM super_class.
PUBLIC SECTION.
METHODS own_method.
ENDCLASS.
Now, as super_class is empty, sub_class does not take over any methods there. In contrast, we add a method own_method specifically to this class.
The following statement sequence then demonstrates exactly what's special with the dynamic calling:
DATA cut TYPE REF TO super_class.
cut = NEW sub_class( ).
CALL METHOD cut->('OWN_METHOD').
" runs sub_class->own_method
The runtime encounters the call method statement. It first inspects the static type of the variable cut, which is super_class. The requested method own_method is not present there. If this was all that happened, the call would now fail with a method-not-found exception. If we wrote a hard-coded cut->own_method( ), we wouldn't even get this far - the compiler would already reject this.
However, with call method the runtime continues. It determines the dynamic type of cut as being sub_class. Then it looks whether it finds an own_method there. And indeed, it does. The statement is accepted and the call is directed to own_method. This additional effort that's happening here is exactly what's described in the documentation as "This method is searched for first in the static type, then in the dynamic type of oref".
What we're seeing here is different from hard-coded method calls, but it is also not "illegal". In essence, the runtime here first casts the variable cut to its dynamic type sub_class, then looks up the available methods again. As if we were writing DATA(casted) = CAST super_class( cut ). casted->own_method( ). I cannot say why the runtime acts this way. It feels like the kind of relaxed behavior we usually find in ABAP when statements evolve throughout their lifetime and need to remain backwards-compatible.
There is one detail that needs additional addressing: the tiny word "then" in the documentation. Why is it important to say that it first looks in the static type, then in the dynamic type? In the example above, it could simply say "and/or" instead.
Why this detail may be important is described in my second answer to your question, which I posted some days ago. Let me wrap it up shortly again here, so this answer here is complete. Given an interface with a method some_method:
INTERFACE some_interface PUBLIC.
METHODS some_method RETURNING VALUE(result) TYPE string.
ENDINTERFACE.
and a class that implements it, but also adds another method of its own, with the exact same name some_method:
CLASS some_class DEFINITION PUBLIC.
PUBLIC SECTION.
INTERFACES some_interface.
METHODS some_method RETURNING VALUE(result) TYPE string.
ENDCLASS.
CLASS some_class IMPLEMENTATION.
METHOD some_interface~some_method.
result = `Executed the interface's method`.
ENDMETHOD.
METHOD some_method.
result = `Executed the class's method`.
ENDMETHOD.
ENDCLASS.
Which one of the two methods is now called by CALL METHOD cut->('some_method')? The order in the documentation describes it:
DATA cut TYPE REF TO some_interface.
cut = NEW some_class( ).
DATA result TYPE string.
CALL METHOD cut->('SOME_METHOD')
RECEIVING
result = result.
cl_abap_unit_assert=>assert_equals(
act = result
exp = `Executed the interface's method` ).
Upon encountering the call method statement, the runtime checks the static type of the variable cut first, which is some_interface. This type has a method some_method. The runtime thus will continue to call this method. This, again is standard object orientation. Especially note how this example calls the method some_method by giving the string some_method alone, although its fully qualified name is actually some_interface~some_method. This is consistent with the hard-coded variant cut->some_method( ).
If the runtime acted the other way around, inspecting the dynamic type first, and the static type afterwards, it would act differently and call the class's own method some_method instead.
There is no way to call the class's own some_method, by the way. Although the documentation suggests that the runtime would consider cut's dynamic type some_class in a second step, it also adds that "In the dynamic case too, only interface components can be accessed and it is not possible to use interface reference variable to access any type of component."
The only way to call the class's own method some_method, is by changing cut's type:
DATA cut TYPE REF TO some_class.
cut = NEW some_class( ).
DATA result TYPE string.
CALL METHOD cut->('SOME_METHOD')
RECEIVING
result = result.
cl_abap_unit_assert=>assert_equals(
act = result
exp = `Executed the class's method` ).
This is rather about interface implementations than class inheritance. What the ABAP language help means is this:
Suppose you have an interface that declares a method
INTERFACE some_interface PUBLIC.
METHODS some_method RETURNING VALUE(result) TYPE string.
ENDINTERFACE.
and a class that implements it, but alongside also declares a method with the same name, of its own
CLASS some_class DEFINITION PUBLIC.
PUBLIC SECTION.
INTERFACES some_interface.
METHODS some_method RETURNING VALUE(result) TYPE string.
ENDCLASS.
CLASS some_class IMPLEMENTATION.
METHOD some_interface~some_method.
result = `Executed the interface's method`.
ENDMETHOD.
METHOD some_method.
result = `Executed the class's method`.
ENDMETHOD.
ENDCLASS.
then a dynamic call on a reference variable typed with the interface will choose the interface method over the class's own method
METHOD prefers_interface_method.
DATA cut TYPE REF TO zfh_some_interface.
cut = NEW zfh_some_class( ).
DATA result TYPE string.
CALL METHOD cut->('SOME_METHOD')
RECEIVING
result = result.
cl_abap_unit_assert=>assert_equals(
act = result
exp = `Executed the interface's method` ).
ENDMETHOD.
This is actually the exact same behavior we are observing with regular calls to methods, i.e. if we provide the method's name in the code, not in a variable.
Only if the runtime cannot find a method with the given name in the static type will it start looking for a method with that name in the dynamic type. This is different from regular method calls, where the compiler will reject the missing some_interface~ and require us to add an alias for this to work.
By the way, as some people brought it up in the comments, the "static" here does not refer to CLASS-METHODS, as opposed to "instance" methods. "Static type" and "dynamic type" refer to different things, see the section Static Type and Dynmic Type in the help article Assignment Rules for Reference Variables.

Extending a generics class with nested generics

is there a way in typescript to extend a class in this way:
class ChildClass<Wrapper<A>> extends SuperClass<A>
This doesn't work but the idea would be to wrap the generics type into a known construct. Here are the docs:
https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md
This sounds a bit similar to this issue:
Can you subclass a generics class with a specific typed class?
I don't do much oop so I'm not very familiar with stuff like covariance and contravariance, any help would be appreciated.
It maeks no sense to write ChildClass<Wrapper<A>> before the extends, because there you declare the generic type parameters. That means you can give them a name and, if you need to, a constraint (for example ChildClass<A extends Wrapper>). What does Wrapper<A> mean in this context? The compiler can make no sense of it.
What is absolutely possible is to use Wrapper<A> on the other side of the extends, because there A is not a (formal) type parameter, but a type argument. That means you are using the type parameter previously defined and there you can generate new types with it.
So depending on what you actually want to do, there are two options for you:
A is assignable to Wrapper
When you want to make sure the A is a Wrapper or a derived class, use a generic constraint:
class ChildClass<A extends Wrapper> extends SuperClass<A>
A is a type argument of Wrapper<>
If Wrapper<> is itself a generic class or interface and you want to use A as its type argument, do this:
class ChildClass<A> extends SuperClass<Wrapper<A>>

How to put class dynamically in <>

I know there are various capabilities in Java with reflection.
For example:
Class<?> clazz = Class.forName("java.util.Date");
Object ins = clazz.newInstance();
I wonder if I could pass class dynamicaly in some method declaration in <> tags (or there is other way to do it if it must be fixed). I would like to change that class declaration dynamicaly; because I would like to write generic method for all types of classes.
In there, I have this:
List<Country>
Can I write it something diffrent with reflection? For example can it be somehow be achieved to pass class as parameter (or how else should be this done):
List<ins>
? I would appreciate examples.
This cannot be done because generics are a compile time feature. Once code is compiled, the only place where generics are exists are at method signatures, and they are only used for compiling new code.
When working with reflection, you are basicly working with raw types, and need to code according to that, that means, you can cast the returned result of newInstance() to the list type your need, for example:
List<Country> ins = (List<Country>)clazz.newInstance();
This is a safe operation to do, because you know at that point its empty, and isn't passed to any outside code.
I don't think this is possible. Generics in Java are implemented in a way that prohibits runtime access.
Generics are there so that the compiler can verify correct typing, but are no longer present at runtime (this is called "type erasure"). Reflection deals with the runtime representation of types only. As far as I know the only case where reflection has to deal with generics is to find out "fixed" type parameters of sub-classes, e.g. when you have class Bar<T> and class Foo extends Bar<String>, you can find out that the T of Bar is fixed to String in Foo using reflection. However, this is information found in the class file, too. Except that, reflection can only see or create raw-types.

How to read a private attribute of an object without a getter in ABAP

Is there any way to get the value of an objects' private attribute without a getter. Modifying the class is not permitted in any shape or form.
Please find below an example class with a private attribute.
CLASS counter DEFINITION.
PUBLIC SECTION.
METHODS: set IMPORTING value(set_value) TYPE i.
PRIVATE SECTION.
DATA count TYPE i.
ENDCLASS. "counter DEFINITION
CLASS counter IMPLEMENTATION.
METHOD set.
count = set_value.
ENDMETHOD. "set
ENDCLASS. "counter IMPLEMENTATION
How can I get the value of count? Inheriting from counter will not work because count is private, not protected.
Unfortunately not, I have tried this myself in many different ways none of which work:
Having a standard super class - the super class cannot access the
private attributes of subclasses dynamically
Making a subclass will never work since it can only access protected
Attempting to use the unit test framework doesn't work. I tried to
call the kernel modules that allow access to private data but to no
avail.
You are basically flat out of luck. There is one obscure option though depending on the class you are trying to access. Some classes have interfaces specified as friends and if you implement that interface you can access their private data (the ALV on 7.20 is like this) but unfortunately this will only work in a few limited cases.
Runtime type services are the abap's equivalent of reflection.
They allow You nearly to scan every object, and mostly even modify it at runtime. As far as i know, the visibility of attributes does not matter. But be careful.
And read about the various classes, because there are many, each specified to work on a special type of dataopbject ( structs, objects, etc)
http://wiki.scn.sap.com/wiki/pages/viewpage.action?pageId=42965
You could make a sub class, re-implement the setter and set a second variable, then call the parent method. Be aware of the ramifications of having two variables holding the same stuff... Please see vwegert's comments and see if you really want to because it's generally not a great idea and it breaks the rules of OO.
CLASS counter_sub DEFINITION INHERITING FROM counter.
PUBLIC SECTION.
data count2 type i read-only.
METHODS: set REDEFINITION.
ENDCLASS. "counter_sub DEFINITION
CLASS counter_sub IMPLEMENTATION.
METHOD set.
count2 = set_value.
super->set( set_value ).
ENDMETHOD. "set
ENDCLASS. "counter_sub IMPLEMENTATION

naming a method - using set() when *not* setting a property?

Is setX() method name appropriate for only for setting class property X?
For instance, I have a class where the output is a string of an html table. Before you can you can call getTable, you have to call setTable(), which just looks at a other properties and decides how to construct the table. It doesn't actually directly set any class property -- only causes the property to be set. When it's called, the class will construct strHtmlTable, but you can't specify it.
So, calling it setTable breaks the convention of get and set being interfaces for class properties.
Is there another naming convention for this kind of method?
Edit: in this particular class, there are at least two ( and in total 8 optional ) other methods that must be called before the class knows everything it needs to to construct the table. I chose to have the data set as separate methods rather than clutter up the __construct() with 8 optional parameters which I'll never remember the order of.
I would recommend something like generateTable() instead of setTable(). This provides a situation where the name of the method clearly denotes what it does.
I would probably still use a setTable() method to actually set the property, though. Ideally, you could open the possibility of setting a previously defined table for further flexibility.
Yes, setX() is primarily used for setting a field X, though setX() may have some additional code that needs to run in addition to a direct assignment to a field. Using it for something else may be misleading to other developers.
I would definitely recommend against having a public setTable() and would say that setTable() could be omitted or just an unused private method depending upon your requirements.
It sounds like the activity to generate the table is more of a view of other properties on the object, so you might consider moving that to a private method on the object like generateHtmlTable(). This could be done during construction (and upon updates to the object) so that any subsequent calls to getTable() will return the the appropriate HTML.