在一种情况下,将Kotlingenerics约束为非null
我有一个genericstypes( T: Any?
),我需要约束在一种情况下永远不会为null
:
class Repository { // 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() val fromFoo: String = repository.getFromFoo() // Returns a non-null String. val fromBar: String = repository.getFromBar() // How do I make this work? val repository = Repository() val fromFoo: String? = repository.getFromFoo() // Returns a nullable String. val fromBar: String = repository.getFromBar() // How do I make this return a non-null String?
虽然我会理想地将这些重构成单独的types(如FooRepository
和BarRepository
),有什么办法来获得这种types的约束function?
你需要的是typesT & Any
– genericsT
和Any
的交集。 它代表了T
不能包含空值的T
子types。
不幸的是,交集types和这个交集特别是在Kotlin中是不可指定的,这意味着你不能将函数的返回types声明为T
非可为子types。
做相反的事情。 假设您的genericstypes不可为空:
class Repository { fun getFromFoo(): T? { ... } fun getFromBar(): T { ... } } val repository = Repository() val fromFoo: String? = repository.getFromFoo() val fromBar: String = repository.getFromBar()
class Repository { // T may only be a non-null type. fun getFromFoo(): T? {} // This may return null. fun getFromBar(): T {} // This is never null. } val repository = Repository() val fromFoo: String? = repository.getFromFoo() val fromBar: String = repository.getFromBar()
需要一个非nulltypes。 你可以通过T?
选择性地指出可空性T?
vs你的方法/属性。
编辑:根据评论中的问题澄清修订的解决方案
我现在的印象是,你想要一个方法总是返回一个非空值,即使T是一个可为空的types。 简短的答案是否定的,没有办法做到这一点。
但是,您可以定义两种generics:
class Repository { fun getFromFoo(): T {} fun getFromBar(): N {} } val repository = Repository() val fromFoo: String? = repository.getFromFoo() val fromBar: String = repository.getFromBar()
是一个选项,但不强制N
是非空types的。
是另一种选择,这迫使N
是一个不可空的types,但它不再被迫扩展T
选择你的毒药。
这使得构建存储库丑陋,但让你容易在所有的调用网站非空。
您不应该使用可为空的types进行参数化。 您应该使用非nulltypes,然后在真正需要的地方明确可空性:
class Repository { fun getFromFoo(): T? { TODO() } fun getFromBar(): T { TODO() } }
你说T
应该是一个非空types( T: Any
),并且说getFromFoo()
可能返回T?
,这工作完全正常。
重构为两个单独的类将是一个更好的主意,但是由于您不希望可以使用两个genericstypes:
class Repository { fun getFromFoo(): T? { /* ... */ } fun getFromBar(): S { /* ... */ } }