Generics 要求可能为null的泛型不为null

Generics 要求可能为null的泛型不为null,generics,kotlin,Generics,Kotlin,在Kotlin中,我能够编写一个函数,该函数从一个超类中获取一个可能为null的泛型参数——我们称之为Person——并返回完全相同的类型,如下所示: fun <V: Person?> identity(arg1: V): V = arg1 val p1: Person? = identity(null) // works fine val p2: Person = identity(Person()) // works fine val p3: Person = identity

在Kotlin中,我能够编写一个函数,该函数从一个超类中获取一个可能为null的泛型参数——我们称之为
Person
——并返回完全相同的类型,如下所示:

fun <V: Person?> identity(arg1: V): V = arg1

val p1: Person? = identity(null) // works fine
val p2: Person = identity(Person()) // works fine
val p3: Person = identity(null) // does not work
fun <V: Person> identity(nullable: V?, nonNullable: V): V? = TODO() // do something

val p1: Person? = identity(null, Person()) // works fine
val p2: Person? = identity(Person(), Person()) // works fine
val p3: Person? = identity(null, null) // does not compile as second argument is null

并不是说两个参数应该具有完全相同的类型,所以
不起作用。

如果我理解您想要实现的目标,您可以将
V
的上限更改为不可为null的值,并在需要时显式将其标记为可为null,如下所示:

fun <V: Person?> identity(arg1: V): V = arg1

val p1: Person? = identity(null) // works fine
val p2: Person = identity(Person()) // works fine
val p3: Person = identity(null) // does not work
fun <V: Person> identity(nullable: V?, nonNullable: V): V? = TODO() // do something

val p1: Person? = identity(null, Person()) // works fine
val p2: Person? = identity(Person(), Person()) // works fine
val p3: Person? = identity(null, null) // does not compile as second argument is null
fun标识(可空:V?,不可空:V):V?=TODO()//做点什么
val p1:人?=identity(null,Person())//工作正常
val p2:人?=identity(Person(),Person())//工作正常
val p3:人?=标识(null,null)//由于第二个参数为null,因此无法编译

但是请注意,您需要决定是否返回可为null的或不可为null的结果,而在原始示例中,根据实际的
V
是否可为null来推断结果。

如果我理解您想要实现的目标,您可以将
V
的上限更改为不可为null的值,并在需要时显式将其标记为可为null,如下所示:

fun <V: Person?> identity(arg1: V): V = arg1

val p1: Person? = identity(null) // works fine
val p2: Person = identity(Person()) // works fine
val p3: Person = identity(null) // does not work
fun <V: Person> identity(nullable: V?, nonNullable: V): V? = TODO() // do something

val p1: Person? = identity(null, Person()) // works fine
val p2: Person? = identity(Person(), Person()) // works fine
val p3: Person? = identity(null, null) // does not compile as second argument is null
fun标识(可空:V?,不可空:V):V?=TODO()//做点什么
val p1:人?=identity(null,Person())//工作正常
val p2:人?=identity(Person(),Person())//工作正常
val p3:人?=标识(null,null)//由于第二个参数为null,因此无法编译

但是请注意,您需要决定是返回可为null的结果还是不可为null的结果,而在你最初的例子中,这是根据实际的
V
是否可为空推断出来的。

是的,我也考虑过,但对我来说,返回值与第一个参数相同这一点非常重要。你能添加一些第二个有趣的例子来澄清你想要什么吗。@Cilenco我相信你能通过Kotlin contracts API表达这一点。我确实试过那种方法,但我什么都做不到,因此,对于这样的功能来说,现在还为时过早,或者我在测试中遗漏了一些东西。我也考虑过这一点,但对我来说,返回值与第一个参数相同,这一点非常重要。你可以添加一些例子,说明你的第二个乐趣,以澄清你想要什么。@Cilenco我相信你可以通过Kotlin合同表达出来应用程序编程接口。实际上我已经尝试过这种方法,但是我无法得到任何有效的东西,所以对于这样的功能来说太早了,或者我在测试中错过了一些东西