Students Save 30%! Learn & create with unlimited courses & creative assets Students Save 30%! Save Now
Advertisement
  1. Code
  2. Kotlin
Code

Kotlin从头开始:更多功能的乐趣

by
Difficulty:IntermediateLength:LongLanguages:
This post is part of a series called Kotlin From Scratch.
Kotlin From Scratch: Packages and Basic Functions
Kotlin From Scratch: Advanced Functions

Chinese (Simplified) (中文(简体)) translation by Zhang Xiang Liang (you can also view the original English article)

Kotlin  是一种编译为Java字节码的现代编程语言。它是免费的,  开源,并有望使Android开发更有趣。

前面的文章中,您了解了Kotlin中的软件包和基本功能。函数是Kotlin的核心,所以在这篇文章中我们会更仔细地看看它们。我们将在Kotlin中探索以下几种功能:

  • 顶层函数
  • lambda表达式或函数文字
  • 匿名功能
  • 本地或嵌套功能
  • 中缀函数
  • 成员函数

Kotlin的所有功能都可以让你惊叹!

1.顶层函数

顶层函数是Kotlin包内的函数,它们在任何类,对象或接口之外定义。这意味着它们是您直接调用的函数,无需创建任何对象或调用任何类。 

如果您是Java编码器,您知道我们通常在帮助器类中创建实用程序静态方法。 这些辅助类没有做任何事情 - 它们没有任何状态或实例方法,它们只是作为静态方法的容器。一个典型的例子是包中的Collectionsjava.util和静态方法。

Kotlin中的顶层函数可以替代我们在Java中编写的帮助程序类中的静态实用程序方法。我们来看看如何在Kotlin中定义一个顶层函数。

在上面的代码中,我们在名为UserUtils.kt的文件中  定义了一个包com.chikekotlin.projectx.utils,并且还定义了在同一个包和文件中调用的顶级实用程序函数checkUserStatus()。为了简洁起见,这个非常简单的函数返回字符串“online”。 

接下来我们要做的是在另一个包或文件中使用这个实用函数。 

在前面的代码中,我们将该函数导入到另一个包中,然后执行它!正如你所看到的,我们不需要创建一个对象或者引用一个类来调用这个函数。

Java互操作性

鉴于Java不支持顶层函数,Kotlin编译器将创建一个Java类,并将单个顶层函数转换为静态方法。在我们自己的情况下,生成的Java类是UserUtilsKt使用静态方法  checkUserStatus()。 

这意味着Java调用者可以通过引用其生成的类来简单地调用该方法,就像其他任何静态方法一样。 

请注意,我们可以使用@JvmName注释来更改Kotlin编译器生成的Java类名称。

在上面的代码中,我们应用了@JvmName注释并UserUtils 为生成的文件指定了一个类名  。还要注意,这个注释放在包定义之前的Kotlin文件的开头。 

它可以像这样从Java引用:

2. Lambda表达式

Lambda表达式(或函数文字)也不会绑定到任何实体,例如类,对象或接口。 它们可以作为参数传递给其他称为高阶函数的函数(我们将在下一篇文章中进一步讨论这些函数)。lambda表达式仅表示函数的块,并且使用它们可以减少代码中的噪声。 

如果您是Java编码人员,您知道Java 8及以上版本支持lambda表达式。要在支持早期Java版本(如Java 7,6或5)的项目中使用lambda表达式,我们可以使用受欢迎的  Retrolambda库。 

. 关于Kotlin的令人敬畏的事情之一是,lambda表达式是开箱即用的。由于lambda在Java 6或7中不受支持,所以Kotlin可以与它进行互操作,Kotlin在场景后面创建一个Java匿名类。但请注意,在Kotlin中创建lambda表达式与在Java中创建lambda表达式完全不同。

以下是Kotlin中lambda表达式的特征:

  • 它必须被花括号包围{}。
  • 它没有fun关键字。 
  • 没有访问修饰符(私有,公共或受保护),因为它不属于任何类,对象或接口。
  • 它没有功能名称。换句话说,它是匿名的。 
  • 没有指定返回类型,因为它会被编译器推断出来。
  • 参数不被括号包围()。 

而且,更重要的是,我们可以将一个lambda表达式分配给一个变量,然后执行它。 

创建Lambda表达式

现在让我们看一些lambda表达式的例子。在下面的代码中,我们创建了一个没有任何参数的lambda表达式,并为其分配了一个变量  message。然后我们通过调用来执行lambda表达式  message()。 

我们来看看如何在lambda表达式中包含参数。 

在上面的代码中,我们用参数myString和参数类型String创建了一个lambda表达式。正如你所看到的,在参数类型前面有一个箭头:这是指lambda体。 换句话说,这个箭头将参数列表从lambda体中分离出来。为了使它更简洁,我们可以完全忽略参数类型(已由编译器推断)。 

要有多个参数,我们只需用逗号分隔它们。请记住,我们不会将参数列表包装在Java中的括号内。 

但是请注意,如果无法推断参数类型,则必须明确指定它们(如本例中所示),否则代码将无法编译。

将Lambdas传递给函数

我们可以将lambda表达式作为参数传递给函数:这些被称为“高阶函数”,因为它们是函数的函数。这些类型的函数可以接受一个lambda或一个匿名函数作为参数:例如,  last() 收集函数。 

在下面的代码中,我们传递了一个lambda表达式给  last() 函数。(如果您想要复习Kotlin中的集合,请参阅本系列的  第三篇教程)正如名称所示,它会返回列表中的最后一个元素。  last()接受一个lambda表达式作为参数,而这个表达式又接受一个类型的参数  String。它的函数体作为一个谓词在集合中元素的一个子集内进行搜索。这意味着lambda表达式将决定在查找最后一个集合时哪些元素将被考虑。 。 。

让我们看看如何让上面的最后一行代码更具可读性。

如果函数中的最后一个参数是lambda表达式,Kotlin编译器允许我们删除函数括号。正如你可以在上面的代码中看到的那样,我们被允许这样做,因为传递给last()函数的最后一个参数是lambda表达式。 

此外,我们可以通过删除参数类型来使其更加简洁。

我们不需要明确指定参数类型,因为参数类型始终与集合元素类型相同。在上面的代码中,我们调用last了一个String对象的列表集合,所以Kotlin编译器足够聪明,知道参数也是一个String类型。 

it 参数名称

我们甚至可以通过用自动生成的默认参数名称替换lambda表达式参数来进一步简化lambda表达式  it。

该it参数名称是自动生成的,因为  last 可以接受lambda表达式或匿名函数(我们会于短期内)只使用一个参数,它的类型可以通过编译器来推断。  

Lambda表达式中的本地返回

我们从一个例子开始。在下面的代码中,我们将一个lambda表达式传递给 集合intList  上调用的  foreach()函数。 该函数将遍历集合并在列表中的每个元素上执行lambda。如果任何元素被2整除,它将停止并从lambda返回。 

运行上面的代码可能没有给你你可能预期的结果。这是因为return语句不会从lambda返回,而是从包含函数返回  surroundingFunction()!这意味着最后的代码语句surroundingFunction()将不会执行。  。

为了解决这个问题,我们需要通过使用标签或名称标签来明确地告诉它从哪个函数返回。 

在上面更新后的代码中,我们在lambda内的关键字@forEach后立即指定了默认标签return。 我们现在已经指示编译器从lambda返回而不是包含函数  surroundingFunction()。现在surroundingFunction() 将执行最后一个声明  。 

请注意,我们也可以定义自己的标签或名称标签。 

在上面的代码中,我们定义了我们的自定义标签myLabel@ ,然后为return关键字指定它。@forEach编译器为该forEach函数生成的标签不再可用,因为我们已经定义了我们自己的标签。 

但是,当我们很快讨论Kotlin中的匿名函数时,您很快将会看到,如何在没有标签的情况下解决本地返回问题。

3.成员函数

这类函数是在类,对象或接口中定义的。使用成员函数可以帮助我们进一步模块化我们的程序。现在让我们看看如何创建一个成员函数。

该代码片段显示了一个Circle具有成员函数calculateArea()的类(我们将在稍后的帖子中讨论Kotlin类)。该函数需要一个参数radius来计算圆的面积。

为了调用成员函数,我们使用包含类或对象实例的名称带点,后跟函数名称,如果需要传递任何参数。 

4.匿名函数

匿名函数是另一种定义可以传递给函数的代码块的方法。它不受任何标识符的约束。以下是Kotlin中匿名函数的特征:

  • 没有名字
  • 是使用fun关键字创建的
  • 包含一个函数体

因为我们将lambda传递给last()上面的函数,所以我们不能明确返回类型。为了明确返回类型,我们需要使用匿名函数。

在上面的代码中,我们用一个匿名函数替换了lambda表达式,因为我们想要明确返回类型。

在本教程的lambda部分的末尾,我们使用了一个标签来指定从哪个函数返回。在函数中使用匿名函数而不是lambda forEach() 函数可以更简单地解决这个问题。返回表达式从匿名函数返回,而不是从周围的函数返回,在我们的情况下是这样  surroundingFunction()。  .

5.本地或嵌套功能

为了进一步实现程序模块化,Kotlin为我们提供了本地功能 - 也称为嵌套功能。本地函数是在另一个函数内声明的函数。 

正如你可以在上面的代码段观察,我们有两个单行功能:calCircumference()与calArea()嵌套的内部printCircumferenceAndAread()函数。 嵌套函数只能在封闭函数中调用,而不能在外部调用。同样,嵌套函数的使用使我们的程序更加模块化和整齐。 

我们可以通过不明确地向它们传递参数来使我们的本地函数更加简洁。这是可能的,因为本地函数可以访问封闭函数的所有参数和变量。让我们看看现在在行动中:

正如你所看到的,这个更新后的代码看起来更具可读性并减少了我们以前的噪音。虽然本例给出的封闭函数很小,但在更大的封闭函数中可以分解为更小的嵌套函数,但此功能确实可以派上用场。 

6.中缀函数

infix符号可以让我们轻松调用一个参数的成员函数或扩展功能。除了函数是单参数之外,还必须使用infix修饰符定义函数。 要创建中缀函数,需要两个参数。第一个参数是目标对象,而第二个参数只是传递给函数的单个参数。 

创建一个中缀成员函数

让我们看看如何在一个类中创建一个中缀函数。在下面的代码示例中,我们创建了一个  具有可变  kotlinScore 实例字段的类Student。 我们通过infixfun关键字之前使用修饰符创建了中缀函数。正如您在下面看到的,我们创建了一个中缀函数addKotlinScore(),该函数获取分数并添加到  kotlinScore 实例字段中。 

调用中缀函数

我们来看看如何调用我们创建的中缀函数。要在Kotlin中调用中缀函数,我们不需要使用点符号,并且我们不需要用括号包装参数。 

在上面的代码中,我们调用了中缀函数,目标对象是  student,而double  95.00 是传递给函数的参数。 

明智地使用中缀函数可以使我们的代码比正常风格更具表现力和更清晰。在Kotlin编写单元测试时我们会非常感激(我们将在未来的帖子中讨论Kotlin的测试)。

to缀函数

在Kotlin中,我们可以通过使用to中缀函数而不是Pair构造函数来创建一个更简洁的Pair实例  。(在幕后,to创建了一个  Pair 实例。)注意,该to函数也是一个扩展函数(我们将在下一篇文章中讨论这些)。

现在我们来比较Pair使用to中缀函数创建实例并直接使用Pair执行相同操作的构造函数创建一个实例,并查看哪一个更好。

正如你在上面的代码中看到的那样,使用 to中  缀函数比直接使用Pair 构造函数创建  Pair 实例更简洁  。 请记住,使用to中缀函数234是目标对象,  String “尼日利亚”是传递给函数的参数。另外请注意,我们也可以这样做来创建一个Pair类型:

Ranges and Collections文章中,我们通过给Kotlin创建了一个地图集合,其中第一个值是关键字,第二个是值。我们还通过使用to中缀函数和Pair构造函数来创建一个映射,以创建各个对。

在上面的代码中,我们Pair使用中to缀函数创建了一个以逗号分隔的类型列表,  并将它们传递给该mapOf()函数。我们也可以通过直接使用Pair每对的构造函数来创建相同的地图。

正如您再次看到的那样,坚持使用to 中缀函数比使用Pair构造函数的噪音少。 

结论

在本教程中,您了解了可以使用Kotlin中的函数执行的一些很酷的事情。我们涵盖:

  • 顶层函数
  • lambda表达式或函数文字
  • 成员函数
  • 匿名功能
  • 本地或嵌套功能 
  • 中缀函数

但那不是全部!还有更多要学习Kotlin的功能。因此,在下一篇文章中,您将学习函数的一些高级用法,例如扩展函数,高阶函数和闭包。再见!

要了解有关Kotlin语言的更多信息,我建议访问  Kotlin文档。或者在Envato Tuts +上查看我们的其他一些Android应用程序开发帖子!

Envato qr branded
关注我们的公众号
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.