英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论