I'm creating a class that inherits from a parent class with protected instantiation. The super class has a static method that provides an instance of the class.
The following code causes a run-time error MOVE_CAST_ERROR:
data: o_child type ref to zchild.
o_child ?= zparent=>provide_instance( ).
I have also tried:
data: o_parent type ref to zparent,
o_child type ref to zchild.
o_parent = zparent=>provide_instance( ).
o_child ?= o_parent.
I have succesfully down-casted with other object types in the past - does anyone have an idea what to look for in ZPARENT or ZCHILD that may make the two classes incompatible?
Currently ZCHILD only has one extra method, which if added to the super class would break the abstraction of the class, so I'm not that keen to do it.
I didn't do any object oriented coding in abap. Nor much abap programming. But I think that this is a typical oo scenario. So here is my guess.
You can't cast an object to what it ain't.
You have created an instance of the parent class. Now the child class has the property of "myCandy" that the parent class don't have. So your object don't have this property. And then you cast it to child. What the poor run time has to do when you ask for ( or change ) the "myCandy" property? It can do nothing. So it disallow this cast.
The cast is only possible if the object was instantiated as the child and then it was casted to the parent object and then back again to the child object. The child has everything the parent has so there is no problem with this path.
Related
How to mimic simple inheritance with parent and child class constructors in Lua?
I will provide and accept and answer and would greatly appreciate if you commented on it or edited interesting information into it.
This is a guide for mimicking basic parent/child class inheritance in Lua.
I assume that basic features and syntax of Lua are known to the reader. The following statements are especially important:
There are no classes or objects in Lua, just tables.
A table can have a metatable.
If the metatable mt of a table t contains the __index metamethod (thus mt.__index), access to a non-existent key in t is attempted to be resolved via what's assigned to mt.__index.
If t calls a function t.foo() like this t:foo() then t itself is passed to foo() as the first argument called self. Inside the function, t itself is accessible as self.
Base class
Code
Base = {}
function Base:new(name)
Base.__index = Base
local obj = {}
setmetatable(obj, Base)
obj.name = name
return obj
end
function Base:sayName()
print(self.name..": My name is "..self.name..".")
end
Because of what the function Base:new(name) does, Base can now be seen as a new class, with Base:new(name) being its constructor. Remember that Base really is a table that sits somewhere in memory, not some abstract "class blue print". It contains a function Base:sayName(). This is what we could call a method with respect to OOP lingo.
But how does Base:new(name) let Base act like a class?
Explanation
Base.__index = Base
The Base table gets an __index metamethod, namely itself. Whenever Base is used as a metatable, searches to a non-existent index will be redirected to... Base itself. (Wait for it.) The line could also be written as self.__index = self, because Base calls :new(name) and thus self is Base therein. I prefer the first version, because it clearly shows what's happening. Also, Base.__index = Base could go outside of Base:new(name), however, I prefer having all the "set up" happen inside one scope (the "constructor") for the sake of clarity.
local obj = {}
setmetatable(obj, Base)
obj is created as a new empty table. It will become what we think of as an object of the "class" Base. The Base is now the metatable of obj. Since Base has an __index, access to non-existent keys in obj well be redirected to what is assigned to Base.__index. And since Base.__index is Base itself, access to non-existent keys in obj will be redirected to Base (where it would find Base:sayName(), for instance)!
obj.name = name
return obj
The obj (!) gets a new entry, a member, to which the constructor parameter is assigned. The obj is then returned and is what we would interpret as an object of class Base.
Demonstration
b = Base:new("Mr. Base")
b:sayName()
This prints "Mr. Base: My name is Mr. Base." as expected. b finds sayName() via the metatable-__index mechanism as described above, because it doesn't have such a key. sayName() lives inside Base (the "class table") and name inside b (the "object table").
Child class
Code
Child = {}
function Child:new(name, age) -- our child class takes a second argument
Child.__index = Child
setmetatable(Child, {__index = Base}) -- this is different!
local obj = Base:new(name, age) -- this is different!
setmetatable(obj, Child)
obj.age = age
return obj
end
function Child:sayAge()
print(self.name..": I am "..tonumber(self.age).." years old.")
end
The code is almost exactly the same as for the base class! Adding a second parameter in the Child:new(name, age) (i.e. the constructor) is not especially noteworthy. Base could also have had more than one parameter. However, the second and third line inside Child:new(name, age) were added and that is what causes Child to "inherit" from Base.
Note that Base may contain Base.__index, which makes it useful when used as a metatable, but that it has no metatable itself.
Explanation
setmetatable(Child, {__index = Base})
In this line, we assign a metatable to the Child class table. This metatable contains an __index metamethod, which is set to the Base class table. Thus, the Child class table will try to resolve access to non-existent keys via the Base class table. Thus, the Child class table has access to all of its own and all of Base's methods!
local obj = Base:new(name, age)
setmetatable(obj, Child)
In the first line, a new Base object table is created. At this point, its __index metamethod points to the Base class table. However, right in line two, its metatable is assigned to the Child class table. The reason why obj does not lose access to Base class methods lies in the fact that we redirected non-successful key accesses in Child to Base (by giving Child the proper metatable) just before! Since obj was created as a Base object table, it contains all of its members. Additionally, it also contains the members of a Child object table (once they are added in the Child:new(name, age) "constructor". It finds the methods of the Child class table via its own metamethod. And it finds the methods in the Base class table via the metamethod in the Child class table.
Note: With "Base object table" I mean the table that is returned by Base:new(name). With "Base class table" I mean the actual Base table. Remember, there are no classes/objects in Lua! The Base class table and the Base object table together mimic what we think of as OOP behavior. The same goes for Child, of course.
Also, scoping the assignment of Child's metatable inside Child:new(name, age) allows us to call Base's "constructor" and pass the name argument to it!
Demonstration
c = Child:new("Mrs. Child", 42)
c:sayName()
c:sayAge()
This prints "Mrs. Child: My name is Mrs. Child." and "Mrs. Child: I am 42 years old." as expected.
Conclusion
The sections above described how to implement OOP behavior in Lua. It is important to understand that
Base methods live inside the Base class table
Base members live inside the Base object table returned by Base:new()
Child methods live inside the Child class table
Child members live inside the Child object table returned by Child:new()
Referencing the correct tables is accomplished by the table's metatables.
All class tables assign themselves to their __index key. When used as metatables, they refer to themselves (i.e. where the class methods live). There is only one class table per "class".
Base classes don't have a metatable. They are used as metatables.
Child class tables also have a metatable, namely {__index = Base} (which redirects calls to the Base class table, i.e. where the Base class methods live).
All object tables assign their corresponding class tables as metatables. Since the class tables have set their __index metamethod, calls to the object tables can be redirected to the class tables where the class methods live. If it is a child class table (which means it also has a metatable), the redirection can happen even further. There can be arbitrarily many object tables.
Use the image above to follow along: What happens if a Child object table c tries to access a Base method, e.g. c:sayName()? Well: Has c a sayName() key? No. Does it have a metatable? Yes: Child (the Child class table). Does Child have an __index metamethod? Yes. Where does it point? To Child itself. Does Child have a sayName() key? No. Does Child have a metatable? Yes. Does it have an __index metamethod? Yes. Where does it point? To the Base class table. Does it have a sayName() key? Yes! :-)
Note
I am no Lua expert! I have only done some scripting in Lua so far, but over the last days I tried to wrap my mind around this. I found a lot of different, sometimes confusing solutions and finally arrived at this, which I would call the most simple but transparent solution. If you find any errors or caveats do not hesitate to comment!
I am using newest Delphi 10.3.3
I have several main classes, which are extended from same parent class and also some, let's call it, Reflection classes, which has also same parent. I want instance of main class to have link to corresponding reflection instance, but I run to this issue (I simplified it to this example):
Main classes:
TMainClass = class
Link: TReflectionClass;
end;
TCarMainClass = class(TMainClass)
Link: TCarReflectionClass;
end;
Reflection classes:
TReflectionClass = class;
TCarReflectionClass = class(TReflectionClass);
The problem lies in Link field. I want Link field in TCarMainClass to be directly defined as TCarReflectionClass to avoid type-casting on lot of pieces of code (and also risking some errors), however if I define class like this, TCarMainClass.Link just hides TMainClass.Link - it is defined as different field with same name. That is not good because it consumes extra memory and mainly I can't access that field from parent class, which I want (as pointer to generic instance).
Of course I can solve this by making field private of common type and define property setter/getter which handles re-typing in each class. But that is lot of extra code for these classes and also overhead on each get/set because of calling getter/setter methods.
My question is - is there some easy hack I missed, to tell compiler I want field in child class to occupy same memory location as certain field in parent class?
Thanks
and mainly I can't access that field from parent class
While it's true that parent class can't access the descendant's field, there is nothing preventing you from synchronizing the 2.
procedure TCarMainClass.SetLink(const Value : TCarReflectionClass);
begin
FLink := Value;
TMainClass(Self).FLink := Value;
end;
Now, if you absolutely require no additionnal memory use and no setters, the only remaining option (that I can think of at this time) is as GolezTrol suggested, generics.
TMainClass<T : TReflectionClass> = class
Link: T;
end;
TCarMainClass = class(TMainClass<TCarReflectionClass>)
end;
But that would probably break your design though, because TCarMainClass would be incompatible with TMainClass<TReflectionClass>. (if you want to understand why, search for the terms covariance/contravariance).
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
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.
What's the difference between the child of a class and an instance of a class? Both seem to inherit code from their "parent". Is the difference that an instance of a class is executed code, versus a child of a class merely being around to create additional instances?
A class is nothing more than a definition, a template, a pattern. An instance of that class is a copy of that definition that has been allocated memory space in which to hold its data. It's like saying a cake is an instance of a cake recipe.
A child of a class is literally that - the parent forms a base definition, which the child then extends or enhances. It's a variation on the parent, much like a chocolate cake is a variation (or it extends) a basic cake recipe.
Note that this very simple explanation of OO concepts hides how this stuff is actually implemented at the machine level. A class can contain methods (operations) - there is only one copy kept of these methods, instantiating a new instance of the class doesn't make a fresh copy of the methods. Instead memory space is allocated to the new instance, and pointers will be used to point to the actual code that should be implemented for each method. Each instance does have its own copy of data (attributes) though.
For example with php:
class A {
//...
}
class B extends A {
//...
}
$a = new A();
We say B is the child of A, $a is an instance of A.