具有子类型的 Kotlin 泛型?
Kotlin generics with subtypes?
我无法理解为什么子类型不能与 Kotlin 泛型一起工作。
假设以下简单场景
class Student : Person()
open class Person
这个有效
fun personOrStudent : Person{
return Student()
}
但这不是
fun <Item:Person> personOrStudent() : Item {
return Student()
}
我不明白为什么。 return 类型 Item 不是类型为 Person 的子类型吗? .我相信语法清楚地表明 Item 将是 Person 的子类型。
但是我得到一个编译时错误,说 expected 是 Person ,而不是 student。
这与协变/逆变有关系吗?
通过将函数定义为参数化,我们基本上意味着我们不知道 Item
的确切类型并且它取决于调用站点。 Student
可能是此函数的有效 return 值,但也可能不是。
考虑这个例子:
class NotAStudent : Person()
personOrStudent<NotAStudent>()
我们期望函数 returns NotAStudent
,但实现 returned Student
。这就是它无法编译的原因。
换句话说:<Item: Person>
并不意味着 Item
只是任何 Person
。这意味着 Item
是 Person
的一个非常特殊的子类型,但我们不知道是哪一个。
另一种解释方式以防有帮助:
不同之处在于,对于泛型,泛型所代表的类型是在调用它的代码中定义的。您的通用函数没有 return 和 Person
。它 return 是调用者要求的任何特定类型。 <T: Person>
表示调用者只能请求 Person 类型或 Persons 的子类型。
open class Person
class Student : Person()
class Teacher: Person()
//...
val teacher = personOrStudent<Teacher>() // The caller is asking for a Teacher.
如果他们要求 Teacher
,学生将是无效响应。
在 real-world 应用程序中,我认为没有理由编写这样的泛型函数,其中泛型类型仅用作 return 类型,而不是参数,因为如果它与任何函数输入无关,则无法 determine/use 请求的类型。但是,对于 reified
类型,这是可能的,因为具体化类型本身就是一个输入。
我无法理解为什么子类型不能与 Kotlin 泛型一起工作。
假设以下简单场景
class Student : Person()
open class Person
这个有效
fun personOrStudent : Person{
return Student()
}
但这不是
fun <Item:Person> personOrStudent() : Item {
return Student()
}
我不明白为什么。 return 类型 Item 不是类型为 Person 的子类型吗? .我相信语法清楚地表明 Item 将是 Person 的子类型。
但是我得到一个编译时错误,说 expected 是 Person ,而不是 student。
这与协变/逆变有关系吗?
通过将函数定义为参数化,我们基本上意味着我们不知道 Item
的确切类型并且它取决于调用站点。 Student
可能是此函数的有效 return 值,但也可能不是。
考虑这个例子:
class NotAStudent : Person()
personOrStudent<NotAStudent>()
我们期望函数 returns NotAStudent
,但实现 returned Student
。这就是它无法编译的原因。
换句话说:<Item: Person>
并不意味着 Item
只是任何 Person
。这意味着 Item
是 Person
的一个非常特殊的子类型,但我们不知道是哪一个。
另一种解释方式以防有帮助:
不同之处在于,对于泛型,泛型所代表的类型是在调用它的代码中定义的。您的通用函数没有 return 和 Person
。它 return 是调用者要求的任何特定类型。 <T: Person>
表示调用者只能请求 Person 类型或 Persons 的子类型。
open class Person
class Student : Person()
class Teacher: Person()
//...
val teacher = personOrStudent<Teacher>() // The caller is asking for a Teacher.
如果他们要求 Teacher
,学生将是无效响应。
在 real-world 应用程序中,我认为没有理由编写这样的泛型函数,其中泛型类型仅用作 return 类型,而不是参数,因为如果它与任何函数输入无关,则无法 determine/use 请求的类型。但是,对于 reified
类型,这是可能的,因为具体化类型本身就是一个输入。