I'm new to the language. When trying to compile a new object type with a method (where the first argument is an instance of my new type), the compiler warned me like this:
Warning: use {.base.} for base methods; baseless methods are deprecated [UseBase]
Base methods correspond to what would be the base class for a method in a single-dispatch language. The base method is the most general application of a method to one or more classes. If you are dispatching on just a single argument, the base method should be associated with the type that would normally be the base class containing the method.
This warning typically happens to me when I define a method on a derived type -- thinking that I'm overriding behavior from a base type -- but the method signature is wrong and I'm effectively not overriding any method, hence the warning.
e.g.,
type
Base = ref object of RootObj
Derived = ref object of Base
method doSomething(b: Base, n: int) {.base.} =
...
# !!! This method gets warning because it's not overriding the base
# !!! doSomething method due to different parameter types
method doSomething(d: Derived, n: string) =
...
Related
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.
I have a generic parent class:
open class Parent<T>{/*...*/}
and I have some derived classes that implement a specific instance of the generic parent:
class Derived1 : Parent<Foo1> {/*...*/}
class Derived2 : Parent<Foo2> {/*...*/}
where Foo1 and Foo2 are some classes defined elsewhere
I now need to create a function that returns a different derived class based on some input parameter:
fun getDerived(derived: SomeEnumType): Parent{
//return the correct derived class
}
Of course the line above won't compile because Parent requires a generic parameter. The Derived classes are not of the same type, so I wouldn't expect to be able to handle this polymorphically. How can I achieve this? I am familiar with kotlin.Any but this seems like cheating.
If it helps, I am using this pattern to parse json in the correct child class with the gson library (by overriding the deserializer)
You could get away with Parent<*> but if there is a relationship between Foo1 and Foo2 (e.g extending a common interface, Buzz) then you could use something like Parent<out Buzz>.
IIRC, <*> is like Java's wildcard <?>. Not bounding the response type will mean you'll need some type guards at the call site of your function getDerived to make the response inspectable.
I have a class which is the parse result of a string, so I have to enforce the toString() to return that source string instead of those parsed values. It also has custom equals()/hashCode() mechanism. Is there any benefit to still mark it as a data class?
The auto-generated parts of data classes are:
The compiler automatically derives the following members from all
properties declared in the primary constructor:
- equals()/hashCode() pair,
- toString() of the form "User(name=John, age=42)",
- componentN() functions corresponding to the properties in their order of declaration,
- copy() function.
If any of these functions is explicitly defined in the class body or
inherited from the base types, it will not be generated.
The componentN() function enables destructuring like for ((a, b, c) in dataClass) { ... }
However, data classes CANNOT be inherited. (You can define a data class that extends another non-data class though.)
If you think that it is possible that some classes extend your class, then do not make it a data class.
If you think that no class will extend your class in the future, and you maybe need the destruction or copy() function, then make it a data class.
In JsonDeserialize annotation documentation the contentAs field is supposed to define the "Concrete type to deserialize content".
I tried to use this in combination, with either a Converter (via contentConverter field of the same annotation) or a JsonDeserializer (via contentUsing field of the same annotation), by extending either StdConverter or StdDeserializer, respectively, in an attempt to create an agnostic custom deserializer.
I cannot find a way to access the JsonDeserialize#contentAs information inside any of these two classes.
I am aware that the classes I extend from have a type parameter, I just put an Object class there. Documentation states
contentAs Concrete type to deserialize content (elements of a Collection/array, values of Maps) values as, instead of type otherwise declared. Must be a subtype of declared type; otherwise an exception may be thrown by deserializer.
Apparently I am applying the #JsonDeserializer annotation on a Collection of some persistable Class. I want to deserialize each such object, solely by knowing its id. Well, if I could only get that very type I defined in the #JsonDeserializer#contentAs field...
Can anyone tell me if this is possible anyhow?
I managed to implement the agnostic deserializer withou the use of #JsonDeserializer#contentAs after all.
After reading the javadocs of com.fasterxml.jackson.databind.JsonDeserializer I concluded that my custom deserializer should implement the com.fasterxml.jackson.databind.deser.ContextualDeserializer interface.
Inside the implementation of ContextualDeserializer#createContextual(DeserializationContext ctxt, BeanProperty property)
I could finally get access to the class type of the content of the collection, which I applied the #JsonDeserialize annotation on,
by calling:
ctxt.getContextualType().getRawClass()
NOTE that the same call inside the implementation of com.fasterxml.jackson.databind.JsonDeserializer#deserialize(com.fasterxml.jackson.core.JsonParser, com.fasterxml.jackson.databind.DeserializationContext) returned null, hence the need of the aforementioned interface.
All I had to do then is store the returned class in a member field (of type Class< ? >) of the custom deserializer and use it in the execution of JsonDeserializer#deserialize()
The only thing that remains to check is whether an instance of this custom deserializer is shared between threads. I only did some minor checks; I used the same implementation for two different collections of different types. I observed that ContextualDeserializer#createContextual(DeserializationContext ctxt, BeanProperty property) was called once (among multiple deserialization invokations), for each distinct type that was going to be deserialized. After checking during debugging, it seems that the same deserializer object is used for the same type. In my case, since what I store in the member field is this type itself, I don't mind if the same deserializer is used for the same java type to be deserialized because they should contain the same value. So we 're clear on this aspect as well.
EDIT: It appears all I have to do is update the com.fasterxml.jackson.databind.deser.std.StdDeserializer#_valueClass value to the now known class. Since it is final and since the ContextualDeserializer#createContextual(DeserializationContext ctxt, BeanProperty property) returns a JsonSerializer object, which is actually used,
instead of returning "this" serializer I can create a new one, passing the discovered class in the constructor, which actually sets the StdDeserializer#_valueClass to the class I actually want, and I'm all set!
Finally, NOTE that I didn't have to use the #JsonDeserializer#contentAs annotationfield as I get the value from the ctxt.getContextualType().getRawClass() statement inside ContextualDeserializer#createContextual(DeserializationContext ctxt, BeanProperty property) implementation
I am new to OOP. I am still in a learning phase.
Why do we need constructors, When we can initialize the values of the properties (variables) by writing a "Initialize function"?
Basically why do we write a constructor when we can achieve the same results even by writing a function for initializing the variables?
The constructor IS the "Initialize function"
Rather than calling two functions
object = new Class;
object.initialize();
You just call
object = new Class();
The logic inside the constructor can be identical to the logic inside the initialize function, but it's much tidier and avoids you naming your function initialize(), me naming mine initialize_variables(), and someone else naming theirs init_vars()... consistency is useful.
If your constructor is very large, you may still wish to split variable initialisation into a separate function and calling that function from your constructor, but that's a specific exception to the scenario.
So answer is simple
Why do we write Constructor?
Because in C you can write,
int i;
if write like this In above case data type and variable defines if you define like this memory allocated for i variable.So simple here we define class name and variable name(object name) we can create memory allocated for class name.
Example
myClass objectName;
But in C++ new keyword is used for dynamic memory allocation, so this dynamic memory which we can allocate to our class but here my example myClass is our class and we want to allocate to dynamic memory allocated.
So
myClass objectName = new myClass();
and simply constructor is memory allocation for class variable is called the constructor.`
the role of the constructor is to initialize the variables/values.it is the "initialization function".The only reason i find on why we use a constructor instead of a normal function to initialize the variables is to stop different people from using different function names and avoid ambiguity and it is much more easier to use a constructor which is instantiated automatically as soon as the class is run,instead of having to write a separate code for instantiation.this may seem small and like something that doesn't require much work,but only for a very small program,for larger ones the struggle is real.
It is usual to put mandatory things into the constructor and optional ones into the Initialise function.
For example, consider an amplifier that requires a power source so that would be supplied to its constructor. Logically, you may want to turn it on and set its power level but one could argue that you might not want to do that until later. In pseudo-code:
class Amplifier
{
public Amplifier(PowerSource powerSource)
{
// create amplifier...
}
public int PowerLevel;
public void Initialise()
{
// turn on...
}
}
The example, above, is rather puerile but it illustrates the concepts at play. It is always an issue of design, however, and opinions do vary.
Some classes of object, however, will have to perform obvious set-up operations during their construction phase. In these cases, the requirement to have a constructor is very easy to understand. For example, if your object might require a variable amount of memory, the constructor would be a logical place to allocate it and the destructor or finaliser would be a logical place to free it up again.
Even if you don't use constructor it will call implicitly by your language translator whenever you create object.Why?
The reason is that it is used for object initialization means the variable(instance) which we declare inside our class get initialized to their default value.
class Person {
//Class have two parts
//1.Data(instance variable)
//2.Methods(Sub-routine)
String name;
int age;
}
public class Stack{
public static void main(String[] args){
Person person1 = new Person();
System.out.println("Name: "+person1.name);
System.out.println("Age: " + person1.age);
}
}
Output- Name: null
Age: 0
"null" and "0" are default values which are impicitly set by default constructor.
When we initialize a class by creating an instance or object the constructor is called automatically. This is very helpful when we need a huge amount of code to be executed every time we create an object.
The best use of constructor can be seen when we create a " graphical user interface". While building a GUI for an application we need to separate the code for designing the GUI and the business logic of the application. In such a case we can write the code for designing GUI, in a constructor and business logic in respective methods. This make the code tidy and neat too.
Also when an object is created the global variables can be initialized to their default values using constructor. If we don't initialize the global variables, then the compiler will do it implicitly by using the default constructor.
So constructor is a very wise concept which appears to be an idiosyncrasy at first but as you code further and more and more you will realize it's importance.
Because constructors are exactly for that: to avoid using an "initialize function"
Plus you can have have as many constructors as you want: you juste feed them some parameters, depending how you want to inialize your object.
Constructor is a special member function which has same name as class name and called whenever object of that class is created. They are used to initialize data field in object.
Constructor has following properties:
It has same name as class name.
It is called whenever object of a class is created.
It does not have return type not even void.
It can have parameters.
Constructor can be overloaded.
Default constructor is automatically created when compiler does not find any constructor in a class.
Parameterized constructor can call default constructor using this() method.
A constructor can be static for static data field initialization.
It is not implicitly inherited.
For More Info
https://en.wikipedia.org/wiki/Constructor_(object-oriented_programming)