That's right. The reason for this is that it's a lot of boilerplate if you were to require listing every relevant Impl block as a superclass of your struct. I also, as a bonus, like enforcing a consistent class naming style.
Why not just give `Impls` a special attribute:
class ExampleImpl(Foo, metaclass=Impl):
target = Bar
Or do the entire thing via a decorator: @impl_for(Bar)
class ExampleImpl(Foo):
pass
?EDIT: actually, your examples wouldn't work as-is, since it would result in circular references (something Python isn't well-equipped to handle). Your target names would need to be strings instead of the actual class.
EDIT2: I have updated the code to allow for another syntax:
class AnyImplNameIWant(MyTrait, metaclass=Impl, target="MyStruct"):
...
It would certainly be nicer if `MyStruct` didn't need to be a string of course. I really think these options are mostly down to taste, so I'll just have to trust that this alternative reads sufficiently more nicely. @impl(Sheep, Animal)
class ImplAnimalForSheep:
...
or something?It probably needn't even be a separate class - just decorate the relevant methods (or the `Sheep` class itself) `@impl(Animal)` and check the necessary ones are implemented on instantiation.