As my first rust project, I have a simple program I’m converting from python to rust. It uses a library that’s an interface to an obscure database engine.
I have 3 similar resources that are giving me trouble: Table, Cursor and Statement.
A Table is almost interchangeable with a Cursor, but there are some special operations that only apply to a Table.
In python I subclassed Table from Cursor and implemented 2 mixins: CursorStatementMixin and TableStatementMixin, to implement functions that apply to those combinations.
In rust since I can’t subclass I figured I’d implement the following traits: CursorTrait, CursorStatementTrait and TableStatementTrait.
Cursor will then impl CursorTrait and CursorStatementTrait.
Table will impl CursorTrait and TableStatementTrait and it’s own unique functions.
Statement will impl CursorStatementTrait and TableStatementTrait and it’s own unique functions.
Here’s the problems I’m having with this approach:
- I can’t figure out how to define data members in a trait. This is NOT that big a deal, but I’m mentioning it for completeness. I have to add the following to each of the three structs:
handle: ADSHANDLE; // type ADSHANDLE = usize;
- I can’t access data members of self. I have a common init() function that needs to run for both Cursor and Table to cache a list of the fields in the table. Since this is a private function, I could obviously move this to a generic, but there will be other functions that need to be public and need to access fields inside the Cursor/Table.
error[E0609]: no field
fields on type
127 | self.fields = Vec::new();
- I have to explicitly import traits in user code for the methods to be visible. This just feels ugly. I get that I would need to do this if I wanted to use them in generics, but I feel that I shouldn’t have to just to call methods on the object that are defined by the trait.