Filling in the gaps
Here are some additions to the previous article on zoop.
Concepts that are easily confused
What is T
in this: *T
in inherited methods?
This T
can be the class itself, or any subclass, because the inheritable function will be expanded on the class itself and all subclasses, and when expanding, the class itself or the subclass is substituted into T
.
Therefore, in an inheritable method, before accessing the data and methods of Self
, this
must be statically converted to Self
through cast() before use. This is also why the parameter is called this
instead of self
, because the parameter passed in is not necessarily of the Self
type.
What is rootptr
?
rootptr
exists for type conversion. When a subclass pointer is converted to a parent class, how can it be converted back to the subclass? The current pointer points to the parent class's data. To be able to convert back to the subclass, the parent class's data must have the original pointer to the subclass data. This pointer is rootptr
, which is stored in the mixin
field of the parent class. The following detailed example will help you better understand what rootptr
is. Assuming that SubClass
is a subclass of Base
, the following logic holds:
const t = std.testing;
var sub: *SubClass = try SubClass.new(allocator);
var base: *Base = sub.cast(Base);
const psub: *anyopaque = @ptrCast(sub);
const typeinfo: *const zoop.TypeInfo = zoop.typeInfo(SubClass);
const iobj:IObject = sub.cast(IObject);
const ibase:IObject = base.as(IObject).?;
const sub_rootptr: *anyopaque = sub.mixin.meta.?.rootptr.?;
const sub_typeinfo: *const zoop.TypeInfo = sub.mixin.meta.?.typeinfo;
const base_rootptr: *anyopaque = base.mixin.meta.?.rootptr.?;
const base_typeinfo: *const zoop.TypeInfo = base.mixin.meta.?.typeinfo.?;
try t.expect(sub_rootptr == psub)
try t.expect(base_rootptr == psub)
try t.expect(iobj.ptr == psub)
try t.expect(ibase.ptr == psub)
try t.expect(sub_typeinfo == typeinfo)
try t.expect(base_typeinfo == typeinfo)
Description
- The
rootptr
of an object created by new() points to the address of the object itself, andtypeinfo
points toTypInfo
of the object type rootptr
of any type of object that the object is converted to still points to the address of the object created by new(), andtypeinfo
still points toTypeInfo
of the type of the object created by new()- The
ptr
of any type of interface to which the object is cast still points to the address of the object created by new() - The
ptr
of any type to which the object is converted and any interface to which the object is converted still points to the address of the object created by new()
Conclusion: rootptr
is the address of the object created by new(), and type conversion will not affect this value.
PS: The same is true for objects created by make().