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

poohbar

07/09/2021, 9:20 PM
how could I make this a singleton? it seems like
object
can’t do generics?
Copy code
class Mapper<T : Account> : RecordMapper<Record, T> {
    override fun map(record: Record?): T? {
        TODO("Not yet implemented")
    }
}
Even better, I really just need a function, where the input is
Record
and the output is
T: Account
how do I declare that?
Ideally I need something like this:
Copy code
private val MAPPER: (Record) -> Account = { record: Record ->
    TODO("Not yet implemented")
}
But the output should be
T: Account
, not
Account
d

Dominaezzz

07/09/2021, 9:23 PM
Check out the implementation of
emptyList<T>()
.
p

poohbar

07/09/2021, 9:25 PM
I think I got it, I can just do this:
Copy code
fun <T : Account> mapToAccount(record: Record): T {
    TODO("Not yet implemented")
}
and then pass it as
::mapToAccount
well now i dont understand this
Copy code
fun <T : Account> mapToAccount(record: Record): T {
    val x: Account = Account(...)

    return x // error here
}
why doesn’t
Account
fit into
T
? 😮
d

Dominaezzz

07/09/2021, 9:33 PM
I think you need
in
or
out
.
p

poohbar

07/09/2021, 9:33 PM
maybe i am putting it in the wrong place but it says:
Variance annotations are only allowed for type parameters of classes and interfaces
trivial example:
Copy code
open class Person

fun <T: Person> foo(): T {
    return Person()
}
d

diesieben07

07/09/2021, 9:40 PM
Function references cannot be generic in this way. As soon as you do
::mapToAccount
the
T
gets bound to a concrete value. For example:
val foo: (Record) -> SomeAccountSubclass = ::mapToAccount
binds
T
as
SomeAccountSubclass
.
(Record) -> T
is not a valid type.
So when you want to store it in a reference, you have to choose a concrete type for
T
.
So really you do not want a singleton, because a singleton by definition means that
T
is always the same and as such redundant...
👆 1
e

ephemient

07/09/2021, 9:55 PM
well, if you have your variance right, it would be fine to write a singleton
Copy code
object Mapper : RecordMapper<Record, Nothing>
but there isn't too much you could do with that
d

diesieben07

07/09/2021, 9:57 PM
Yes, it could never return anything
j

jbnizet

07/09/2021, 10:05 PM
@poohbar your function’s return type is T. T can be any class that extends Person: the caller of the function decides which class it is. So it could be a Child, an Adult, a Doctor... anything that extends Person. For example:
val doctor: Doctor = foo<Doctor>()
.` So returning an instance of Person is incorrect: a Doctor is a Person, but a Person is not a Doctor.
e

ephemient

07/09/2021, 10:47 PM
hence why
Nothing
works: it is a subtype of every other type. of course, there are no actual instances of Nothing, so returning is not possible (only abnormal termination or non-termination), but it's the only type that works
p

poohbar

07/10/2021, 10:26 PM
maybe that’s why the
emptyList()
is implemented as:
Copy code
internal object EmptyList : List<Nothing>
strange
e

ephemient

07/11/2021, 1:35 AM
not strange at all,
List<Nothing>
is a
List<T>
because
Nothing
is a
T
and
List<out T>
is covariant
it may help you to think: you can
get(): T
, for any type
T
, out of a `List<Nothing>`… with type safety. of course, at runtime, you can't "get" anything from an empty list, but that doesn't matter to the types
2 Views