英文:
Kotlin extension function for nullable types ONLY
问题
fun String.ext(): Unit = TODO()
fun String?.nullExt(): Unit = TODO()
英文:
Examine this code:
fun f(nullString: String?, nonNullString: String) {
nullString.ext() // Error: Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
nullString.nullExt() // OK, nullabilities match
nonNullString.ext() // OK, nullabilities match
nonNullString.nullExt() // Expected error: nullExt is only applicable to String?
}
I would like to write two function signatures that makes the first and last function call not compile.
This makes the first line a compile error, but the last line still compiles:
fun String.ext(): Unit = TODO()
fun String?.nullExt(): Unit = TODO()
As far as I understand this works because "String extends String?", so defining an extension on String? is similar to defining one on CharSequence. Is there a way to prevent this from compiling?
答案1
得分: 2
以下是要翻译的内容:
A possible solution is to forbid the compiler to pick the "super" implementation, by declaring a more specific one:
fun String.ext(): Unit = TODO()
fun String?.nullExt(): Unit = TODO()
@Deprecated(
message = "nullExt is only applicable to nullable receivers.",
level = DeprecationLevel.ERROR,
replaceWith = ReplaceWith("")
)
fun String.nullExt(): Unit =
error("This should never be called.")
Note: String! will resolve to String overload.
A real use case in case anyone is wondering:
fun <T : Any?> T?.orError(message: String): T & Any =
this ?: error(message)
@Deprecated(
message = "orError is only applicable to nullable receivers.",
level = DeprecationLevel.ERROR,
replaceWith = ReplaceWith("")
)
fun <T : Any> T.orError(message: String): Nothing =
error("This should never be called.")
we wouldn't want somethingNonNull.orError() because in that case orError() will never execute and therefore it is dead code.
英文:
A possible solution is to forbid the compiler to pick the "super" implementation, by declaring a more specific one:
fun String.ext(): Unit = TODO()
fun String?.nullExt(): Unit = TODO()
@Deprecated(
message = "nullExt is only applicable to nullable receivers.",
level = DeprecationLevel.ERROR,
replaceWith = ReplaceWith("")
)
fun String.nullExt(): Unit =
error("This should never be called.")
Note: String! will resolve to String overload.
A real use case in case anyone is wondering:
fun <T : Any?> T?.orError(message: String): T & Any =
this ?: error(message)
@Deprecated(
message = "orError is only applicable to nullable receivers.",
level = DeprecationLevel.ERROR,
replaceWith = ReplaceWith("")
)
fun <T : Any> T.orError(message: String): Nothing =
error("This should never be called.")
we wouldn't want somethingNonNull.orError() because in that case orError() will never execute and therefore it is dead code.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论