The same way the OOP compilers implement them, with v-tables. Basically the compiler makes a table of function pointers so calls can be resolved (not sure resolved is the correct term) at runtime.
In Zig or any other C like language without "interfaces", you would implement the V-table by hand, which is a common idiom in Zig.
Let'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
I'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 Zig or any other C like language without "interfaces", you would implement the V-table by hand, which is a common idiom in Zig.