interfaces ---------- alternative 1: place function pointer directly in the object ------------------------------------------------------------ pros: simple fast(little indirection) cons: wastes space extending an interface breaks the ABI of all subtypes namespace File = { typedef this = ( Reader base, Writer base, const int mode, () *close(File* this), ); } alternative 2: use a vtable --------------------------- pros: uses only one pointer per instance of each interface cons: one extra pointer lookup namespace File = { typedef this = ( interface, // generates the required interface pointer Reader base, Writer base, const int mode, // interface methods are inserted into the vtable. () interface close(File* this), // we could also use "virual" as the keyword () virtual close(File* this), ); } namespace File = { const typeinst VTable vtable = ( () close(File* this) = File.close, ); typedef this = ( VTable *interface, Reader base, Writer base, const int mode, ); } File a = File.open("test.txt"); a.*.close(); alternative 3: use an independent vtable ---------------------------------------- pros: only one pointer needed per object! cons: one extra pointer is needed everywhere an object implementing the interface is referenced. alternative 4: don't use interaces directly ------------------------------------------- pros: no extra language features very clear what's going on the "interface" can check the parameters and then call the real implementation cons: would most likely require more code should interfaces be "fake is-a" (=has-a) or real "is-a" -------------------------------------------------------- "is-a" implies "has-a", because if an object doesn't have the data of the base class, then it can't work in place of the inherited class. a class can "have" an interface. Syntax for type 4 interfaces ---------------------------- namespace util { typedef iterable[T,E] = interface ( iterator[???,E]^ get_iterator(T^ this), ); typedef iterator[I,E] = interface ( bool next_element(var I^ this, var E^ result), ); } namespace range { implements iterator[range,int]; bool next_element(var range^ this, var int^ result) { ... } } namespace iter_printer[I,E] { () print(interface[iterator[I,E]] iter); // translated to //() print((var I^ value, iterator:interface[I,E]^ if_iterator) iter); }