Use generics to allow return types of implementations to be themselves
Move tests to separate package to avoid accessing package-private code