Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin and generic constructors leave me baffled

Not understanding Kotlin in combination with Generics.

I was trying to move some of my java towards kotlin. Couple of those classes are spring-data repositories and a generic service that takes as generic parameter a type of repository, e.g.:

@Transactional
interface ForumRepository : CrudRepository<Forum, Long> {
    fun findByName(name: String): Forum?
}

Then the GenericKotlinService :

abstract class GenericKotlinService<T>(val repository: CrudRepository<Any, Serializable>) {
    fun <T> findOne(id: Serializable): T {
        return repository.findOne(id) as T
    }
    fun delete(id: Any) {
        repository.delete(id)
    }
}

However, now when I try to create a service that uses this generic service with a specific crudRepository I always get errors, e.g.

class ForumService @Autowired constructor(repository: ForumRepository) : GenericKotlinService<Forum>(repository) {
    open fun findByName(name: String) = repository.findByName(name)
}

or

class ForumService : GenericKotlinService<Forum> {
    @Autowired
    constructor(repository: ForumRepository) : super(repository)
    open fun findByName(name: String) = repository.findByName(name)
}

The error is

required CrudRepository<Forum, Long> but got a ForumRepository. 

When I use the following java GenericService:

public abstract class GenericService<T> {
    private final CrudRepository repository;
    public GenericService(CrudRepository repository) {
        this.repository = repository;
    }
    public T findOne(Serializable id) {
        return (T) repository.findOne(id);
    }
    public void delete(Serializable id) {
        repository.delete(id);
    }
}

and use this one in the ForumService:

class ForumService @Autowired constructor(val repository: ForumRepository) : GenericService<Forum>(repository) {
    open fun findByName(name: String) = repository.findByName(name)
}

everything works. I do not see how I can use my GenericKotlinService instead?

like image 738
Ronald Avatar asked Dec 07 '25 07:12

Ronald


1 Answers

The thing is that ForumRepository is not CrudRepository<Any, Serializable>. But it can be convertible to CrudRepository<Any, Serializable> if both type parameters are in out positions. So you can either define the CrudRepository in the following way

interface CrudRepository<out T, out U>

or accept CrudRepository with out type parameters in GenericKotlinService constructor

abstract class GenericKotlinService<T>(
    val repository: CrudRepository<out Any, out Serializable>
)
like image 139
Michael Avatar answered Dec 09 '25 19:12

Michael



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!