Blog › ICP guides
ooc developer on retainer: vtable dispatch, class system, rock compiler, and ooc object-oriented C programming on monthly retainer
September 26, 2026 · ~15 min read
An ooc plugin system was built around a class hierarchy of data parsers. The base class DataParser defined a func parse(input: String) -> Data method that provided a default implementation. A subclass CsvParser was written to override parse with CSV-specific logic. The developer stored a CsvParser instance in a variable typed as DataParser and called parse through that reference. In ooc, methods declared with func are dispatched through a vtable: when you call a method on an object through a parent-class reference, the runtime looks up the actual method implementation in the vtable of the object’s true class. For the vtable to contain the subclass override, the subclass must declare extends ParentClass in its class definition header. The developer had written CsvParser: class { func parse(input: String) -> Data { ... } } — a valid class declaration, but without extends DataParser. Because the extends keyword was missing, CsvParser was an independent class with no inheritance relationship to DataParser; it was not a subclass, its vtable was not populated with the overridden parse method, and the call through the DataParser reference dispatched to DataParser.parse instead of CsvParser.parse. Wrong dispatches: 3 call sites. The ooc developer on retainer diagnosed the missing extends declaration: in ooc, a class that overrides a parent method but does not declare extends ParentClass is not a subclass; the vtable dispatch system has no knowledge of the override, and parent-reference calls always reach the parent implementation. Adding extends DataParser to the CsvParser declaration registered the override in the vtable and fixed all three call sites. Wrong dispatches: 3 → 0.
The work log entry read “fixed parser dispatch, 6h.” It names the result and duration. It cannot explain why the bug was silent rather than a compile error — ooc does not require that a class intended as a subclass use extends; a class declared without extends is a valid standalone class; the method named parse inside CsvParser compiled without error because it was a valid method declaration on an independent class, not a failed override attempt; the only indication of the problem was runtime behavior where the parent implementation ran instead of the subclass implementation. It cannot explain how ooc’s vtable model differs from a language like C++ — in C++, the compiler enforces the inheritance relationship at the point of assignment to a parent-typed pointer (a CsvParser* without inheritance to DataParser cannot be assigned to a DataParser* without an explicit cast, which would fail or warn); in ooc, the type system is more permissive, and storing an object in a parent-typed variable without a true inheritance relationship may succeed silently, with the wrong vtable being used at dispatch time. It cannot explain the rock compiler’s .use file system — ooc dependencies are declared in .use files that specify the library name, version, source directories, and C compilation flags; updating a dependency requires updating the .use file and re-running rock; the .use file is the build manifest for ooc projects and must be kept in sync with the actual source tree. It cannot explain cover-based C interop — cover CStruct from CStructName { field: Int } creates an ooc wrapper for a C struct, allowing ooc code to read and write fields through the ooc type system while the underlying memory layout matches the C struct. The 6 hours of dispatch model analysis, vtable inheritance audit, and extends declaration correction are invisible in the diff.
ooc class system: extends inheritance, func vtable dispatch, init constructors, and This reference
ooc classes are declared with the ClassName: class { ... } syntax. Inheritance uses SubClass: class extends ParentClass { ... }. The extends clause is the mechanism that registers the subclass in ooc’s object model: without it, the class has no parent and its methods are not considered overrides. Methods declared with func are dispatched through the vtable and support polymorphism: calling a func method on an object through a parent-class reference dispatches to the most-derived implementation registered in the vtable. Methods that are not declared with func are static functions associated with the class but not dispatched through the vtable; they cannot be overridden by subclasses in the polymorphic sense. Constructors are declared with init: init: func (param: Int) { ... }. Multiple constructors are differentiated by a suffix: init: func ~withName(name: String) { ... }. Inside a class body, This refers to the current class type, allowing self-referential return types and factory methods that work correctly in subclasses. The super() call invokes the parent class constructor or method, preserving the parent initialization chain.
The final keyword marks a method as non-overridable: a final func method() declaration in a parent class prevents subclasses from overriding it, and the vtable entry is fixed at compile time. This is the ooc mechanism for sealing hot paths: methods that are called in tight loops and whose polymorphic dispatch overhead matters can be marked final to allow the compiler to generate a direct call instead of a vtable lookup. ooc is compiled by the rock compiler, which translates ooc source to C source code. The generated C uses a struct-based object representation with an embedded vtable pointer as the first field; the vtable is a struct of function pointers populated at class registration time. ooc’s closest retainer neighbors are C developer retainers (ooc compiles to C and the interop story is C-centric) and D developer retainers (both are systems-level object-oriented languages with GC and C interop), but ooc’s specific vtable registration model where extends is mandatory for override registration, the cover type for C struct wrapping, and the .use file build manifest system make the retainer work distinct in inheritance correctness, C interop design, and build system configuration.
ooc rock compiler, .use files, cover types, and generic class design
The rock compiler takes ooc source files and generates C code that can be compiled with any standard C compiler. The compilation workflow is rock -v to compile with verbose output, or rock . to compile the current directory. rock --backtrace adds source-level stack trace information to the generated C, making runtime errors easier to diagnose. The --gc=none flag disables the Boehm garbage collector and requires manual memory management; the default is to use Boehm GC, which automatically collects unreachable ooc objects. Dependencies in ooc are declared in .use files: a mylib.use file specifies the library name, version constraints, source directories, include paths, and C linker flags needed to use the library. An ooc file imports a dependency with use mylib; the rock compiler reads the corresponding .use file to find the source and headers. Keeping .use files accurate is the build system work of an ooc project: when a dependency is updated, the .use file must reflect the new version and any changed paths.
ooc’s cover type provides a zero-overhead wrapper for C structs and primitive types. cover CPoint from CPoint_s { x, y: Int } creates an ooc type CPoint that maps directly to the C struct CPoint_s with integer fields x and y; reading and writing the fields through ooc incurs no overhead because the cover is a direct alias for the C memory layout. extern declarations bind C functions into ooc: malloc: extern func (size: SizeT) -> Pointer makes the C malloc function callable from ooc code. The combination of cover and extern is the standard ooc C interop pattern: wrap the C struct with a cover, bind the C functions with extern, and use them from ooc code through the ooc type system. Generic types in ooc are declared with angle brackets: Box: class <T> { value: T }. The SDK provides ArrayList<T> for dynamic arrays and HashMap<K, V> for hash maps. Version blocks version(linux) { ... } provide conditional compilation based on platform, and multiple platform-specific implementations can coexist in the same file under different version blocks, which is the pattern for platform-specific C interop.
How HourTab tracks ooc developer retainer hours
ooc retainer work carries the invisible-hours problem specific to the vtable dispatch model: missing the extends declaration produces no compile error and no runtime error; the program executes correctly in the sense that it runs without crashing, but the wrong method implementation is called, which means the bug manifests as incorrect output rather than a program fault. The plugin system described above — where CsvParser defined a parse method but was missing extends DataParser, causing the parent implementation to be called instead of the override — is the most common correctness issue in ooc code written by developers from languages where the inheritance relationship is inferred from method signature matching or where the compiler enforces the relationship at assignment: in ooc, the class declaration header is the definitive source of the inheritance relationship, and a missing extends is not a warning or an error but a different program semantics. Diagnosing this requires knowing that ooc’s vtable is populated at class registration based on the declared inheritance hierarchy, not based on method signature matching, and that a method named identically to a parent method but declared in a class without extends is not an override. A retainer engagement typically involves inheritance audit (every subclass verified to declare extends ParentClass), vtable dispatch audit (every polymorphic call through a parent reference verified to reach the correct implementation), and .use file audit (every dependency verified in the corresponding .use file with accurate paths and flags).
HourTab gives ooc developers a public retainer-hours URL they send to clients — typically teams using ooc for game development via the ooc-lang.org ecosystem, systems programmers using ooc as an object-oriented C alternative for low-level work, and projects that need C interop with an object-oriented layer on top via covers and externs. For ooc retainers, each work log entry should name the mechanism (class: extends inheritance declaration, func vtable dispatch, final non-override, init constructor, This self-type, super() parent call; compiler: rock compilation, .use file, --gc flag, --backtrace debug; interop: cover from C struct wrapping, extern C function binding, version() conditional; generic: MyClass<T> parameterized, ArrayList/HashMap SDK collections), the specific class name, and the before/after wrong-dispatch count. ooc retainers are often compared to C developer retainers for the shared C compilation target and systems programming context, but ooc’s vtable-based class system where extends must be explicit in the class declaration header, the cover type for zero-overhead C struct access, and the .use file dependency manifest make the retainer work distinct in inheritance correctness diagnosis, C interop design, and build system maintenance. HourTab’s work log makes the vtable inheritance audit, cover-based interop design, and .use file maintenance work visible to clients who would otherwise see only the symptom — wrong method being called at runtime with no error — and not understand why the fix required knowing that in ooc, extends in the class declaration header is not optional boilerplate but the mechanism that registers the override in the vtable, and that a class without extends is as different from a subclass as a standalone C struct is from a struct with a vtable pointer.
Track ooc developer retainer hours without the status emails
HourTab gives ooc developers a public URL per client retainer. One link, no login, live burn-down. Your clients stop asking “how many hours do I have left?” and your vtable dispatch audit log — extends inheritance correctness, cover-based C interop design, .use file maintenance — becomes the proof of value that gets the retainer renewed.
See HourTab pricing →FAQ: ooc developer retainers
What does an ooc developer on retainer typically do?
An ooc developer on monthly retainer covers the ooc class system (ClassName: class { ... } declaration; SubClass: class extends ParentClass { ... } inheritance; func vtable dispatch; init constructor; This self-type; super() parent constructor; final non-overridable methods), the rock compiler and .use file system (rock ooc-to-C compilation; .use dependency manifest; SDK module imports; --backtrace debug info; --gc=none manual memory; Boehm GC integration), and ooc types and C interop (Int/Long/Float/Double/Bool/String/Char primitives; Int[] arrays; ArrayList<T>/HashMap<K,V> SDK collections; generic MyClass<T>; cover from C struct wrapping; extern C function binding; version() conditional compilation).
What ooc work is most commonly underlogged in a retainer?
Vtable dispatch diagnosis (CsvParser: class { func parse(...) {} } missing extends DataParser; override not registered in vtable; parent DataParser.parse called through parent reference; wrong dispatches: 3/call site; added extends DataParser to CsvParser declaration; wrong dispatches: 3/call → 0; 5–9 hrs invisible); cover-based C interop design (cover CStruct from CStructName { field: Int }; field layout verification; extern C function binding; .use file dependency declaration; 4–8 hrs invisible); generic type design (MyClass<T> parameterized class; ArrayList<T> vs raw array; HashMap<K,V> key-value; type constraint declaration; 4–7 hrs invisible); GC integration (finalize for resource cleanup; non-GC resource management; --gc=none manual mode; 3–6 hrs invisible).
What are typical ooc developer retainer rates?
Entry-level ooc developers (1–2 years, basic class declarations, func methods, rock compilation) bill at $60–$110/hr. Mid-level ooc systems programmers (2–4 years, vtable inheritance hierarchies, cover-based C struct wrapping, .use file dependency management, generic type design) bill at $95–$175/hr. Senior ooc object-oriented C developers (4–8 years, complex inheritance hierarchies, deep C interop, SDK extension, large-scale ooc architecture) bill at $140–$255/hr. Monthly retainer ranges: $2,000–$3,800/mo advisory (15–25 hrs), $5,500–$14,500/mo for full ooc systems engineering.
What should an ooc developer retainer agreement include?
An ooc developer retainer agreement should specify: class system scope (ClassName: class declaration; extends inheritance; func vtable dispatch; init constructor; This self-type; super() parent call; final non-override); compiler scope (rock compilation; .use dependency manifest; --backtrace debug; --gc option); C interop scope (cover from C struct wrapping; extern C function binding; field layout verification; version() conditional); generic type scope (MyClass<T>; ArrayList/HashMap SDK; type constraints); and hour logging format (dispatch category: vtable inheritance, extends correctness, func registration; interop category: cover declaration, extern binding, .use file; specific class name and before/after wrong-dispatch count).
How should ooc developer retainer hours be logged?
Log each ooc retainer session with: dispatch category (vtable: extends declaration correctness, override registration, func vs non-func method; cover: C struct wrapping, extern C binding, .use file dependency; generic: MyClass<T> instantiation, ArrayList/HashMap usage); the specific class name and before/after wrong-dispatch count (class: CsvParser; missing extends DataParser in declaration; vtable dispatch called DataParser.parse() instead of CsvParser.parse(); wrong dispatches: 3/call site; added extends DataParser to CsvParser: class extends DataParser; wrong dispatches: 3/call → 0); and the before/after metric. Include whether fix required adding extends to class declaration, changing method from non-func to func for vtable registration, adding final to prevent unintended override, or .use file update for new dependency.