我知道如何阅读/解释Java代码,并且可以编写它。但是对于kotlin来说,我是新手,我发现下面的代码很难阅读。也许我缺少该语言的关键概念。
但是,您将如何解释此代码?为了快速有效地理解这段代码,您打算从哪里开始阅读它?左到右?右到左?首先分解参数?看看返回值吗?
inline fun <T : Any, R> ifNotNull(input: T?, callback: (T) -> R): R? {
return input?.let(callback)
}
答案 0 :(得分:4)
因此,就像Java一样,这是一个通用函数。它有两个类型参数T,它们的类型分别为“ Any”(Java中的“ Any”类似于“ Object”)和R。输入参数是可为空的T,如问号所示。可空类型表示该值可以为空。另一个函数参数是一个接受T(不可为null的类型)并返回R的函数。该函数的返回类型为可为null的R。该函数的主体表示,如果input不为null,则将其调用并将其传递给回调并返回该值。如果input为null,则返回null。
答案 1 :(得分:3)
让我们逐一剖析函数定义:
inline
:表示该函数的代码将直接复制到调用站点,而不是像普通函数一样被调用。
fun
:我们正在定义一个函数。
<T : Any, R>
:此函数采用两个通用类型参数,T
和R
。 T
类型仅限于Any
类型(这是Kotlin的Object
类型)。这似乎是多余的,但实际上是说T
不能是可为空的类型(Any?
)。
ifNotNull
:函数的名称。
input: T?
:类型T?
的第一个参数。我们可以在此处将?
放在T
类型上,因为我们在类型声明中将其限制为非空类型。
callback: (T) -> R
:第二个参数的类型为(T) -> R
,它是一种函数类型。这是一种函数类型,它以T
作为输入并返回R
。
: R?
:该函数返回类型为R
或null的值。
return input?.let(callback)
:函数体。 let
函数接受一个函数参数,并用其接收者(input
)对其进行调用,然后返回该函数的结果。 ?
之后的input
说let
仅当input
不为空时才被调用。如果input
为null,则表达式将返回null。
该函数等效于此Java方法(内联和可为空的类型除外):
public <T, R> R ifNotNull(final T input, final Function<T, R> callback) {
if (input == null) {
return null;
}
return callback.apply(input);
}
答案 2 :(得分:2)
Matt的答案可以一口气解释一切。我会尝试看看如何您可能会去阅读这样的代码。
现在跳过第一个单词,最重要的是第二个单词:fun
。因此,整个过程都在定义一个函数。告诉您其余的期望。
花括号告诉您这是一个块函数,而不是单行代码,因此您期望的基本结构为:fun name(params): returnType { code }
。其余的填补了空白! (这符合Kotlin声明的一般模式,该类型在冒号之后排在第二位.Java的对应词当然更像returnType name(params) { code }
。)
与Java一样,尖括号中的内容提供了通用参数,因此我们现在可以略过,直接进入下一个最重要的位,即所定义函数的名称 :ifNotNull
。
通过这些,我们可以阅读其余内容。 inline
是一个简单的修饰符,告诉您该函数将由编译器内联。 (这可以启用某些功能,并限制其他功能,但我现在不必担心。)
<T : Any, R>
给出函数使用的通用参数类型。第一个是T
,它必须是Any
或子类型;第二个是R
,不受限制。
({Any
类似于Java的Object
,但不能为null
;最上面的类型是相关的Any?
,它也允许null
。因此,除了可空性外,它等效于Java <T extends Object, R>
。)
继续,我们在括号中包含功能参数。同样,有两个:第一个称为input
,类型为T?
,这意味着它可以接受任何类型的T
值,也可以接受null
。第二个参数称为callback
,类型更复杂,为(T) -> R
:它是一个以T
作为参数并返回R
的函数。 (Java没有这样的函数类型,因此可能看起来最奇怪.Java最接近的等效项是Function<R, T>
。)
括号后是该函数本身的返回类型 R?
,这意味着它可以返回R
或null
。
最后,括号中是该函数的实际 code 。该行只有一行,它返回表达式的值。 (其作用是检查input
的值是否为null
:如果是,它将直接返回null
。否则,它将调用参数中给定的callback
函数,将input
作为参数传递,并返回其结果。)
尽管这是一个简短的声明,但它非常抽象并且包含很多内容,因此也难怪您会发现很难! (格式类似于Java方法声明-但Kotlin的表达能力很强,因此等效代码往往比Java短一些。而泛型使其变得更加复杂。)如果您刚开始学习Kotlin,我就是d建议一些简单的方法:-)
(好消息是,就像在Java中一样,您通常不需要阅读stdlib代码。尽管Kotlin的文档注释很少达到Java的示例性水平,但通常仍然足够。)