https://kotlinlang.org logo
#getting-started
Title
# getting-started
a

Aadi Deshpande

12/12/2023, 10:07 PM
Hi folks, somewhat new to Kotlin and I'm struggling with understanding how generics work. For my piece of work, I'm working on extending a java class with generics ( https://micronaut-projects.github.io/micronaut-data/2.3.0/api/io/micronaut/data/repository/CrudRepository.html ) , which I've defined like so :
Copy code
open class FavoritesRepository (val db: Datastore) : CrudRepository<Favorite, UUID> {
where
db
is an instance of a Cloud Datastore ( https://cloud.google.com/java/docs/reference/google-cloud-datastore/latest/com.google.cloud.datastore.Datastore ) In particular, I'm having a hard time understanding why my override of the
save
function doesn't work as I expect it to. The method is:
Copy code
override fun <S: Favorite> save(entity: S): S {
        val key = db.newKeyFactory().newKey(entity.id.toString())
        val favorite = Entity.newBuilder(key).apply {
            set("cityID", entity.cityID)
            set("guid", entity.guid)
            set("email", entity.email)
        }.build()

        return Favorite(cityID=entity.cityID, cguid = entity.cguid,  email = entity.email)
}
In particular the last line produces a
Type mismatch
error, which I can overcome by adding an
as S
to the end of it But, I'd really like to figure out why it doesn't see S and the Favorite as being compatible types. Thanks in advance for any insight you can provide.
k

Klitos Kyriacou

12/12/2023, 10:30 PM
You can't return a
Favorite
because that is a supertype of the expected return type
S
. Imagine code like:
Copy code
val entity: SubtypeOfFavorite = ...
val foo: SubtypeOfFavorite = save(entity)
If your
save
function could compile without error, it would cause chaos because what you would return would be a
Favorite
type, which is not a
SubtypeOfFavorite
. The
save
function is meant to return a value similar to the passed
entity
, perhaps with a key property added. By the way, you don't need to call
apply { set...
- you can just use
.set
in a chain, as
set
returns the receiver object.
h

hho

12/12/2023, 10:37 PM
I guess you're coming from Java – and there it also wouldn't work:
Copy code
public class SomeClass {
	public static class Favorite {}

	public <S extends Favorite> S save(S entity) {
		return new Favorite();
	}
}
Reason being exactly what @Klitos Kyriacou explained 🙂