4 ms·
do you have an example of what that would look like ? I'm a bit confused about when you would construct this table and how one would use it
by bsaul 2y ago
do you have an example of what that would look like ?
I'm a bit confused about when you would construct this table and how one would use it
- genewitch 2y agoI'm not sure what interface means but virtual table in C++ apparently for inheritance, virtual function, and polymorphism (which is a spell or something The rest of OOP is lipstick on arrays and arrays of arrays and "structs / records" or software defined arrays. In my opinion.
- frabert 2y agoLet's say you have an interface 'Reader' with methods 'Read' and 'Close'. In a world where no interfaces exist, every user of a different implementer of this interface would need to know exactly which 'Read' and 'Close' implementations to call, and possibly generate different code for it. In order to make this mechanism generic, you can instead say, "every implementer of the 'Reader' interface has a pointer as its first field, and that pointer leads to an array of two elements: the first element is a pointer to a 'Read' method, the second to a 'Close' method." This way, the user of a Reader knows nothing of the internals of each implementation, other than how to find its methods
- pjmlp 2y agoBasically you have something like typedef struct Writer { int (*method_one)(const char*, int); //... } Writer; void takes_a_writer(const Writer *obj) { // somewhere obj->method_one(buff, buff_size); // ... } // a method implementation int method_one_impl(const char *buff, int n) { //... } // somewhere else Writer w; w.method_one = method_one_impl; //... takes_a_writer(&w); It isn't the best example, but should do the job giving you an overview.
- 2c2c2c 2y agosomethign like this I think. i only dabble in zig/systems stuff so there might be better/more idiomatic ways to write parts const std = @import("std"); // base struct const Animal = struct { // points to the derived struct ctx: *anyopaque, // points to the vtable of the concrete type vtable: *const VTable, // the vtable interface derived struct must implement const VTable = struct { make_noise: *const fn (ctx: *anyopaque, loudness: u32) anyerror!void, }; // call the derived struct's implementation pub fn make_noise(animal: Animal, loudness: u32) anyerror!void { return animal.vtable.make_noise(animal.ctx, loudness); } }; const Dog = struct { // extra data weight: u32, // implement the interface const vtable = Animal.VTable{ .make_noise = &make_noise, }; pub fn make_noise(ctx: *anyopaque, loudness: u32) anyerror!void { const dog: *Dog = @alignCast(@ptrCast(ctx)); std.debug.print("woof {} {}\n", .{ dog.weight, loudness }); } // helper to convert to the base struct pub fn _animal(self: *Dog) Animal { return Animal{ .ctx = @ptrCast(self), .vtable = &vtable, }; } }; const Cat = struct { weight: u32, const vtable = Animal.VTable{ .make_noise = &make_noise, }; pub fn _animal(self: *Cat) Animal { return Animal{ .ctx = @ptrCast(self), .vtable = &vtable, }; } pub fn make_noise(ctx: *anyopaque, loudness: u32) anyerror!void { const cat: *Cat = @alignCast(@ptrCast(ctx)); std.debug.print("meow {} {}\n", .{ cat.weight, loudness }); } }; pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; const alloc = gpa.allocator(); // list of base structs var animal_list = std.ArrayList(Animal).init(alloc); defer { for (animal_list.items) |animal| { if (animal.vtable == &Dog.vtable) { const dog: *Dog = @alignCast(@ptrCast(animal.ctx)); alloc.destroy(dog); } else if (animal.vtable == &Cat.vtable) { const cat: *Cat = @alignCast(@ptrCast(animal.ctx)); alloc.destroy(cat); } } animal_list.deinit(); } for (0..20) |i| { if (i % 2 == 0) { var dog = try alloc.create(Dog); dog.* = Dog{ .weight = @intCast(i) }; try animal_list.append(dog._animal()); } else { var cat = try alloc.create(Cat); cat.* = Cat{ .weight = @intCast(i) }; try animal_list.append(cat._animal()); } } // meows and woofs here for (animal_list.items) |animal| { try animal.make_noise(10); } } ive written a couple and still find them mindbendy
- cgh 2y agoYou can just used tagged enums and the inline else syntax, like this: const Animal = union(enum) { cat: Cat, dog: Dog, pub fn make_noise(self: Animal) void { switch (self) { inline else => |impl| impl.make_noise(), } } };
- 2c2c2c 2y agoiirc there's multiple idioms that are used in different cases. i recall a nice github that laid them all out with use cases but I can't find it