gpt4 book ai didi

Kotlin 扩展函数 - Any 之间的区别?和通用T?

转载 作者:行者123 更新时间:2023-12-04 23:36:14 24 4
gpt4 key购买 nike

我正在做一些有趣的编码,我想知道我应该使用哪一个。两者都试过,他们给了我相同的结果。那么,两者有什么区别呢?

例子:

fun Any?.foo() = this != null

fun <T> T?.foo() = this != null

实际的函数有点复杂,它实际上根据对象的真实类型做一些事情(比如 when 带有一些选项)

最佳答案

第二个函数为您提供了一个在这种特殊情况下没有使用的机会:它将接收器的类型捕获到类型参数 T 中。 ,以便您可以在签名的其他地方使用它,例如在参数类型或返回值类型中,或在函数体中。

作为一个相当综合的例子,一个 listOf(this, this)在第二个函数中输入为 List<T?> ,保留项目类型与接收者类型相同的知识,而第一个函数中的相同表达式将是 List<Any?> .

第一个函数不允许您一般使用接收器类型来存储这种类型的项目,接受相同类型的附加项目作为参数或在函数的返回值类型中使用接收器类型,而第二个函数允许所有这些。

从运行时的角度来看,这些函数是等效的,如 generics are erased from the JVM bytecode编译代码时,您将无法确定类型 T在运行时并根据它采取行动,除非您将函数转换为 inline function with a reified type parameter .

作为一个非常重要的特殊情况,从调用点捕获类型到类型参数允许高阶函数使用 T 接受另一个函数。在其签名中。标准库有一组作用域函数( runapplyletalso )来显示差异。

假设 also 的签名没有使用泛型,看起来像这样:

fun Any?.also(block: (Any?) -> Unit): Any? { ... }

这个函数可以在任何对象上调用,但它的签名并没有表明它是传递给 block 的接收者对象。并从函数返回——编译器将无法确保类型安全,例如,允许在没有类型检查的情况下调用接收器对象的成员:
val s: String = "abc"

// won't compile: `it` is typed as `Any?`, the returned value is `Any?`, too
val ss1: String = (s + s).also { println(it.length) }

// this will work, but it's too noisy
val ss2: String = (s + s).also { println((it as String).length) } as String

现在,捕获类型参数正是表明它在所有三个地方都是相同类型的方式。我们修改签名如下:
fun <T : Any?> T.also(block: (T) -> Unit): T { ... }

并且编译器现在可以推断类型,知道它是相同的类型 T它出现的任何地方:
val s: String = "abc"

// OK!
val ss: String = (s + s).also { println(it.length) }

关于Kotlin 扩展函数 - Any 之间的区别?和通用T?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54113666/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com