Generics 在一种情况下,将Kotlin generic约束为不为null
我有一个泛型类型(Generics 在一种情况下,将Kotlin generic约束为不为null,generics,kotlin,Generics,Kotlin,我有一个泛型类型(T:Any?),我需要在一种情况下将其约束为永远不为null: class Repository<T> { // T may be a non-null or nullable type. fun getFromFoo(): T {} fun getFromBar(): T {} // This is never null. Can I mark it as so? } val repository = Repository<String>(
T:Any?
),我需要在一种情况下将其约束为永远不为null
:
class Repository<T> { // T may be a non-null or nullable type.
fun getFromFoo(): T {}
fun getFromBar(): T {} // This is never null. Can I mark it as so?
}
val repository = Repository<String>()
val fromFoo: String = repository.getFromFoo() // Returns a non-null String.
val fromBar: String = repository.getFromBar() // How do I make this work?
val repository = Repository<String?>()
val fromFoo: String? = repository.getFromFoo() // Returns a nullable String.
val fromBar: String = repository.getFromBar() // How do I make this return a non-null String?
类存储库{//T可以是非null或可为null的类型。
fun getFromFoo():T{}
fun getFromBar():T{}//这从来都不是空的。我可以这样标记它吗?
}
val repository=repository()
val-fromFoo:String=repository.getFromFoo()//返回非空字符串。
val-fromBar:String=repository.getFromBar()//如何使其工作?
val repository=repository()
val fromFoo:字符串?=repository.getFromFoo()//返回一个可为空的字符串。
val-fromBar:String=repository.getFromBar()//如何使此返回为非空字符串?
理想情况下,我会将它们重构为不同的类型(如
foorrepository
和BarRepository
),但有没有办法获得这种类型约束功能?则相反。假设您的泛型类型不可为null:
class Repository<T> {
fun getFromFoo(): T? { ... }
fun getFromBar(): T { ... }
}
val repository = Repository<String>()
val fromFoo: String? = repository.getFromFoo()
val fromBar: String = repository.getFromBar()
类存储库{
fun getFromFoo():T?{…}
fun getFromBar():T{…}
}
val repository=repository()
val fromFoo:字符串?=repository.getFromFoo()
val-fromBar:String=repository.getFromBar()
是一个选项,但它不强制要求N
为不可为空的类型
是另一个选项,它强制N
为不可空类型,但不再强制扩展T
。选择你的毒药
这使得构建存储库变得更加丑陋,但也为您提供了方便,因为它在所有调用站点上都是非空的。重构为两个单独的类是一个更好的主意,但因为您不希望使用两个泛型类型:
class Repository<T, S: Any> {
fun getFromFoo(): T? { /* ... */ }
fun getFromBar(): S { /* ... */ }
}
类存储库{
fun getFromFoo():T?{/*…*/}
fun getFromBar():S{/*…*/}
}
不应使用可为空的类型进行参数化。您应该使用非null类型,然后在真正需要的地方显式地实现null性:
class Repository<out T : Any> {
fun getFromFoo(): T? {
TODO()
}
fun getFromBar(): T {
TODO()
}
}
类存储库{
fun getFromFoo():T{
待办事项()
}
fun getFromBar():T{
待办事项()
}
}
你说
T
应该是一个非空类型(T:Any
),并且说getFromFoo()
可能返回T?
,这非常好。你需要的是类型T&Any
——泛型T
和Any
的交叉点。它表示这样的T
子类型,它永远不能包含空值
不幸的是,在Kotlin中,交集类型,特别是这个交集,目前是不可表示的,这意味着不能将函数的返回类型声明为
t
的不可为null的子类型。那么,存储库的用户不能从非null类型中获得类型安全性好处。考虑ReaviTo.GETFROFFO。这应该会返回一个字符串,但是对于您的代码,它会返回一个字符串吗?不幸的是!也许我遗漏了什么,但从问题来看,这正是你想要的fromFoo
的返回类型可以根据需要为null,而fromBar
的返回类型不可以为null。如果存储库使用不可以为null的类型(如字符串)进行参数化,则两个方法都不能返回null。您尝试过吗。。。?注意T?
的返回类型getFromFoo
。Repository.getFromFoo
的返回类型是String?
。基本上,语言中有一种方法可以说,即使类被参数化为不可为null的类型,方法也可以返回null
。例如,Repository
wheregetFromFoo
返回String?
和getFromBar
返回String
。我想问题是,有没有一种方法可以指示一个方法返回一个不可为null的类型,即使该类是用一个参数化的-简短的回答是否。请查看我对另一个答案的评论。不幸的是,这并不是那么容易。@EricCochran如果评论中的细节是正确的,请编辑这个问题essential@Ilya更新了问题以澄清。OP已经声明这不是他在我的答案评论中想要的。实际上,Kotlin中有一个类型交叉的语法:fun getFromBar():S其中S:T,S:Any{…}
但在这种特殊情况下,它不会有帮助,因为根本不允许类型与类型参数相交
class Repository<T, S: Any> {
fun getFromFoo(): T? { /* ... */ }
fun getFromBar(): S { /* ... */ }
}
class Repository<out T : Any> {
fun getFromFoo(): T? {
TODO()
}
fun getFromBar(): T {
TODO()
}
}