How can I access a super class' method from a child class' method?
Here is an example that illustrates the problem:
Lets say, we have two classes
class parent definition.
public section.
methods f.
endclass.
class child definition inheriting from parent.
public section.
methods f redefinition.
methods g.
endclass.
Now, in the implementation of g we want to call the super class' implementation of f similar to the following syntactically wrong snippet
class child implementation.
method g.
super->f( ). "forbidden: super-> can only be used to call the previous implementation of the same method
endmethod.
endclass.
As stated in the comment, it is not possible to use super->. Can you help?
After some googling, it was suggested to copy the implementation of parent->f into child->g is this really the only way to do it?
The actual use case
#vwegert asked why f is redefined in the first place. In my real use case, parent is a view, and child its extension. child->f is an event handler which is supposed to trigger a popup. child receives a callback when the popup closes in form of a call to g. If g is called, the original implementation parent->f should be called.
You will have to resort to some rather ugly workaround - like set a flag (attribute of the object) in g, then call the redefined f, check whether the flag is set and if it is, only call super->f. It sounds like a very broken design, though. You don't go into details, but I assume you're not able to change the parent view - otherwise I'd strongly suggest to re-think the design because this will lead to unnecessary complexity and technical debt that will very likely introduce bugs and increase maintenance cost.
If you do not mind creating a protected method do_f in the parent class and then delegating the control from f method to do_f method in it. Then the following solution could be quite a neat one. No code duplication, only some additional work in delegating the call in the "original" f method.
REPORT zzy.
CLASS parent DEFINITION.
PUBLIC SECTION.
METHODS f.
PROTECTED SECTION.
METHODS do_f.
ENDCLASS.
CLASS parent IMPLEMENTATION.
METHOD f.
do_f( ).
ENDMETHOD.
METHOD do_f.
WRITE / 'Parent''s f'.
ENDMETHOD.
ENDCLASS.
CLASS child DEFINITION INHERITING FROM parent.
PUBLIC SECTION.
METHODS:
f REDEFINITION,
g.
ENDCLASS.
CLASS child IMPLEMENTATION.
METHOD f.
WRITE / 'Child''s f'.
ENDMETHOD.
METHOD g.
do_f( ).
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
DATA(lo_child) = NEW child( ).
lo_child->g( ).
lo_child->f( ).
Related
Is there any way to let the method of the superclass be overrided, but not called directly?
For example: A inherited from B. There is two methods. One is final and must be called, second is overridable but shouldn't be called, only override.
I tried #available and private but that don't fit. I think that it can be reached by delegate, but maybe there is another way?
For example, you can throw an error in your method that will say that this method shouldn't be called and child class should override it. But, of course, it is no compile time restriction, only runtime.
Also it has sense for you to read discussion here: Abstract functions in Swift Language
I wanna change my titlebar in a dynpro when a specific class method is triggered. So I thought I could call a function in my report, where my dynpro is located, which changes uses the 'SET TITLE' to change the titlebar content.
Is this possible and how exactly? Or is there even a better way?
Thanks!
Use SET TITLEBAR during the PBO processing - it doesn't matter if it is used from a method, a FORM or the module directly. I'd recommend having one single SET TITLEBAR statement that is always called at the same point in the control flow instead of littering the code with SET TITLEBAR statements for better maintainability.
Recently I needed to implement something similar so I defined a class hierarchy where I created an abstract class with a method 'CALL_DYNPRO'. This method is intended to load an specific dynpro in the concrete classes.
So, depending on an action I defined internally I generate the appropriate instance and then the method 'CALL_DYNPRO' loads the dynpro I created with their own gui statuses and titles.
The following is more or less the code I created.
********************************* The abstract class
class lc_caller definition abstract.
public section.
methods: call_dynpro.
endclass.
class lc_caller implementation.
method call_dynpro.
endmethod.
endclass.
********************************* The concrete classes
class lc_caller_01 definition inheriting from lc_caller.
public section.
methods: call_dynpro redefinition.
endclass.
class lc_caller_01 implementation.
method call_dynpro.
call screen 101.
endmethod.
endclass.
class lc_caller_02 definition inheriting from lc_caller.
public section.
methods: call_dynpro redefinition.
endclass.
class lc_caller_02 implementation.
method call_dynpro.
call screen 102.
endmethod.
endclass.
********************************* Factory
class caller definition.
public section.
class-methods call importing i_type type char01
returning value(r_instance) type ref to lc_caller.
endclass.
class caller implementation.
method call.
data: caller1 type ref to lc_caller_01,
caller2 type ref to lc_caller_02.
case i_type.
when '0'.
create object caller1.
r_instance = caller1.
when '1'.
create object caller2.
r_instance = caller2.
when others.
endcase.
endmethod.
endclass.
start-of-selection.
data obj type ref to lc_caller.
obj = caller=>call( '0' ).
obj->call_dynpro( ).
This is the code inside the PBOs.
Dynpro 101
module status_0101 output.
set pf-status 'FORM1'.
set titlebar 'VER'.
endmodule.
Dynpro 102
module status_0102 output.
set pf-status 'FORM2'.
set titlebar 'TRA'.
endmodule.
If tomorrow I need to call another dynpro I create it and then code the concrete class to load it.
Very straightforward and works very nice.
Hope it helps.
Racket's documentation only partially describe what augment and pubment do: augment makes a method that executes after the superclass's version of that method, while pubment makes a method that will implicitly have the augment property if it is defined in a child class.
The docs say absolutely nothing about overment and augride, and I can't guess what they would do based on their names. What are they, and what is the difference between them?
The relatively large family of inheritance functions for Racket's class system is, as you describe, a little confusing, and their somewhat cutesy names don't always help.
In order to understand this, Racket provides two separate mechanisms for method inheritance.
public methods correspond to the classical idea of public methods in other OO models. Methods declared with public may be overridden in subclasses, unless they're declared final, in which case they cannot.
pubment methods are similar, but they cannot be overridden, only augmented. Augmenting a method is similar to overriding it, but the dispatch calls the superclass's implementation instead of the subclass's.
To clarify the difference between overriding and augmentation, when an overridden method is called, the overriding implementation is executed, which may optionally call the superclass's implementation via inherit/super. In contrast, in an augmented method, the superclass's implementation receives control, and it may optionally call the subclass's implementation via inner.
Now, we're also provided public-final, override-final, and augment-final. These are pretty simple. Declaring a method with public-final means it can neither be augmented nor overridden. Using override-final overrides a superclass's public method, but it doesn't allow any further overriding. Finally, augment-final is similar, but for methods declared with pubment, not public.
So then, what about the two weird hybrids, overment and augride?
overment can be used to implement methods initially defined with public. This "converts" them to augmentable methods instead of overridable methods for all the class's subclasses.
augride goes in the opposite direction. It converts an augmentable method to one that is overridable, but the overriding implementations only replace the augmentation, not the original implementation.
To summarize:
public, pubment, and public-final all declare methods that do not exist in a superclass.
Then we have a family of forms for extending superclass methods:
override and augment extend methods declared with public and pubment, respectively, using the relevant behaviors.
override-final and augment-final do the same as their non-final counterparts, but prevent further overriding or augmentation.
overment and augride convert overridable methods to augmentable ones and vice-versa.
For another, fuller explanation, you might be interested in taking a look at the paper from which Racket's model was derived, which is quite readable and includes some helpful diagrams.
It's rather a meta question, so its not that I don't understand polymorphism.
Suppose you have a class and its super class.
The super class has a method print, it prints out "Super".
The sub class overrides this method it prints out "Sub".
If you create two instances, one declared as the super class, the other one as the actual class.
SuperClass superClass = new SubClass();
SubClass subClass = new SubClass();
Now if you work with Eclipse, if you type superClass. and hit ctrl+space, in the list Eclipse says, that the print method belongs to SuperClass.
If you do the same with subClass, eclipse recommends the print method of SubClass.
If you simply use:
superClass.print();
subClass.print();
Then, of course the output will be: SubSub. As it should be.
Would you consider this a mistake in Eclipse? Or there is an explanation for this? Thanks!
Think of code completion as working on the static view, the same view that is also taken by the compiler: completing after superClass. lets you add print() because SuperClass has a method print(). Seeing print() in SuperClass ensures that superClass.print() can be evaluated.
This view is different from the runtime view (what your program actually does), where the JVM will find an instance of SubClass and via dynamic binding invoke the sub class version of print().
Editor, completion and compiler use the static view. If you are interested in the runtime view, you'd typically use the debugger. As a middle road, you may select any method invocation and press Ctrl+T, which gives you the list of all implementations that could possibly be invoked at runtime via this method invocation. But nothing short of the debugger will definitely tell you, which version will actually be called at runtime.
When you ctrl space on superClass, how can we expect IDE to identify for which SubClass u have assigned the variable.
If you have two sub class for a super class, do you expect it to show all the methods from both the sub classes.
What happens if it is not final?
What happens if it s a class level variable where IDE Cannot make sure at that point of execution, which sub class instance being hold.
If you need methods from sub class, then add a instance check, type cast and say ctrl space.
When running FxCop I get the error that interface methods should be callable by child types.
The resolution states the following:
"Make 'MenuPreview' sealed (a breaking change if this class has previously shipped),
implement the method non-explicitly, or implement a new method that exposes
the functionality of 'IComponentConnector.Connect(int, object)'
and is visible to derived classes."
I get this for all classes the derive from Window or some other UI class. Is this a red herring that I can ignore, or is there something I should be doing?
I think the issue is that if an interface is implemented explicitly, it will be impossible for a derived class to both change the interface behavior and make use of the base-class behavior. A common pattern to get around this difficulty in cases where explicit interface implementation would be required is to have the interface do nothing but call a protected virtual method, and have any derived classes that wish to override the behavior of the interface do so by means of the protected virtual method.
Consider IDisposable.Dispose(). If the code in an explicit implementation were actually responsible for performing the disposal, there would be no way for a derived class to add its own dispose logic except by reimplementing IDisposable, and there would be no way for a class which reimplemented IDisposable to access its parent's Dispose method. Although Microsoft could have had IDisposable.Dispose call a protected function with a different name, it opted to use the same name but add a dummy parameter of type Boolean.