How to specify when giving a generic parameter that it should implement some specific creation method? - generic-collections

How to specify when giving a generic parameter that it should implement some specific creation method? as LIST[G -> create make end] doesn't work :-(
In my particular case,
* SMA_INVERTER_MANAGER_CSV has inherited from CONSUMPTION_SECTOR_MODBUS_DEVICE_CSVa list of devices as devices: LINKED_SET[G] as G -> MEASURING_POINT_MODBUS_DEVICE create make_from_file_path end.
I'd like the SMA_INVERTER_MANAGER_CSV class to be able into devices: LINKED_SET[G] to be able to have either JANITZA_DEVICE, SUNSPEC_DEVICE, ABB_DEVICE, etc. Giving the generic parameter as MEASURING_POINT_MODBUS_DEVICE seems to come out of a sense, but how do I specify that I'd like the creation method to be make_from_file_path
Hope the description is sufficient to understand, refactoring I think this question is linked -> explicit creation type not conforming to type of target
The only workaround for the moment I found working for the moment is
class
SMA_INVERTER_MANAGER_CSV
inherit
CONSUMPTION_SECTOR_MODBUS_DEVICE_CSV[SUNSPEC_DEVICE]
create
make
end
but I'd like it to be
class
SMA_INVERTER_MANAGER_CSV
inherit
CONSUMPTION_SECTOR_MODBUS_DEVICE_CSV[MEASURING_POINT_MODBUS_DEVICE]
create
make
end
which would generate a conformance problem because MEASURING_POINT_MODBUS_DEVICE generic parameter doesn't specify make_from_file_path as creation procedure as its deferred

There is more than a conformance problem. MEASURING_POINT_MODBUS_DEVICE is deferred. Therefore, it cannot be used as an actual parameter for CONSUMPTION_SECTOR_MODBUS_DEVICE_CSV. If it were allowed, how would CONSUMPTION_SECTOR_MODBUS_DEVICE_CSV create an instance of a deferred class?
One possible solution — supplying an effective class — is mentioned in the question. Another solution is to add a formal generic parameter to SMA_INVERTER_MANAGER_CSV with the corresponding constraint and to use it for the actual generic of CONSUMPTION_SECTOR_MODBUS_DEVICE_CSV.

Related

How to call remove_column on SALV table?

I want to execute the method remove_column on an instance of cl_salv_column_table but because of its visibility level, I am not able to do so.
Plan:
I already tried inheriting from cl_salv_columns_list and then perform the call inside the remove-method:
CLASS lcl_columns_list DEFINITION INHERITING FROM CL_SALV_COLUMNS_LIST.
PUBLIC SECTION.
METHODS:
remove IMPORTING iw_colname TYPE string.
ENDCLASS.
But apparently my casting knowledge got rusty as I'm not able to figure out an appropriate solution.
This is my current hierarchy - the red arrows show the way I would have to take:
My approach looks like this:
DATA lo_column_list TYPE REF TO lcl_columns_list.
lo_column_list ?= CAST cl_salv_columns_list( lo_columns ).
But it fails with:
CX_SY_MOVE_CAST_ERROR
Source type: \CLASS=CL_SALV_COLUMNS_TABLE
Target type: "\PROGRAM=XXX\CLASS=LCL_COLUMNS_LIST"
Background:
My task is to select all columns of 3 tables (which would be done like SELECT t1~*, t2~*, t3~* ...) as long as their names don't conflict (e.g. field MANDT should only be displayed once). This would require defining a very big structure and kick the size of the selection list to a maximum.
To avoid this, I wanted to make use of the type generated by my inline-declaration. Hiding the individual columns via set_visible( abap_false ) would still display them in the layout manager - which looks really ugly.
Is there any other way to accomplish my target?
Use set_technical( abap_true ) to hide the columns entirely. As for your approach - sorry, inheritance does not work that way - in no statically typed object oriented language that I know. You can't 'recast' an instantiated object to a different class. You would need to modify the framework extensively to support that.

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.

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

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.

Object methods and stats - the best object oriented design approach question

I need to write some instance method, something like this (code in ruby):
def foo_bar(param)
foo(param)
if some_condition
do_bar(param)
else
do_baz(param)
end
end
Method foo_bar is a public api.
But I think, param variable here appears too many times. Maybe it would be better to create an private instance variable and use it in foo, do_bar and do_baz method? Like here: (#param is an instance variable in ruby, it can be initialized any time)
def foo_bar(param)
#param = param
foo
if some_condition
do_bar
else
do_baz
end
end
Which code is better? And why?
Is param replacing part of the state of the object?
If param is not changing the object state then it would be wrong to introduce non-obvious coupling between these methods as a convenience.
If param is altering the state of the object then it may still be bad practice to have a public api altering the state - much better to have a single private method responsible for checking and changing the state.
If param is directly setting the state of the object then I would change the instance variable here but only after checking that the new state is not inconsistent
The first version should be preferred for a couple of reasons. First, it makes testing much easier as each method is independent of other state. To test the do_bar method, simply create an instance of its containing class and invoke the method with various parameters. If you chose the second version of code, you'd have to make sure that the object had all the proper instance variables set before invoking the method. This tightly couples the test code with the object and results in broken test cases or, even worse, testcases that should no longer pass, but still do since they haven't been updated to match how the object now works.
The second reason to prefer the first version of code is that it is a more functional style and facilitates easier reuse. Say that another module or lambda function implements do_bar better than the current one. It won't have been coded to assume some parent class with a certain named instance variable. To be reusable, it will have expected any variables to be passed in as parameters.
The functional approach is the much better approach ... even in object oriented languages.
If you do not need param outside of the foo_bar method the first version is better. It is more obvious what information is being passed around and you are keeping it more thread friendly.
And I also agree with Mladen in the comment above: don't add something to the object state that doesn't belong there.

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.