We can construct an interface without method calling wrappers.
I would call this “C-style” interfaces. Like this:
const log = @import("std").debug.print;
const IFace: type = struct {
funcA: *const fn(*IFace) void,
funcB: *const fn(*IFace) void,
};
const Thing: type = struct {
data: u32,
iface: IFace,
fn init(d: u32) Thing {
return .{
.data = d,
.iface = .{.funcA = myAImpl, .funcB = myBImpl},
};
}
fn myAImpl(i: *IFace) void {
const me: *Thing = @fieldParentPtr("iface", i);
log("I can do A with {}\n", .{me.data});
}
fn myBImpl(i: *IFace) void {
const me: *Thing = @fieldParentPtr("iface", i);
log("Also I can do B with {}\n", .{me.data});
}
};
pub fn main() void {
var t = Thing.init(11);
t.iface.funcA(&t.iface);
t.iface.funcB(&t.iface);
}
Now add wrappers.
const IFace: type = struct {
funcA: *const fn(*IFace) void,
funcB: *const fn(*IFace) void,
fn doA(i: *IFace) void {i.funcA(i);}
fn doB(i: *IFace) void {i.funcB(i);}
};
// Thing is the same
pub fn main() void {
var t = Thing.init(11);
t.iface.doA();
t.iface.doB();
}
So the question - do I understand it correctly that the only purpose of wrappers is to have the ability of using methods calling syntax sugar in main code?