Learn the Kotlin programming language

Kotlin是一种编程语言,被Android开发人员广泛使用。本主题是Kotlin速成班,可帮助您快速入门和运行。

变量声明

Kotlin使用两个不同的关键字来声明变量:val和var。

使用val了其值永远不会改变的变量。您不能将值重新分配给使用声明的变量val。
使用var了其值可以改变的变量。
在下面的示例中,count是类型为变量的变量,Int其初始值为10:

var count: Int = 10

Int是代表整数的类型,整数是可以在Kotlin中表示的许多数值类型之一。类似其他语言,你也可以使用 Byte,Short,Long,Float,并Double根据您的数字数据。

该var关键字,您可以重新分配值count需要。例如,您可以将countfrom 的值更改10为15:

var count: Int = 10
count = 15

但是,某些值不打算更改。考虑一个String称为 languageName。如果要确保languageName始终保持“ Kotlin”的值,则可以languageName使用val关键字进行声明:

val languageName: String = "Kotlin"

这些关键字使您可以明确说明可以更改的内容。根据需要使用它们以发挥自己的优势。如果必须重新分配变量引用,则将其声明为var。否则,请使用val。

类型推断

继续前面的示例,当您将初始值分配给时 languageName,Kotlin编译器可以根据分配值的类型来推断类型。

由于"Kotlin"值是String,因此编译器推断这 languageName也是一个 String。请注意,Kotlin是一种静态类型的 语言。这意味着该类型在编译时已解析,并且永不更改。

在下面的示例中,languageName推断为String,因此您不能调用不属于String该类的任何函数:

val languageName = "Kotlin"
val upperCaseName = languageName.toUpperCase()

// Fails to compile
languageName.inc()

toUpperCase()是只能在类型为的变量上调用的函数 String。由于Kotlin编译器将其推断languageName为a String,因此您可以安全地调用toUpperCase()。inc()但是,它是一个Int运算符,因此不能在上调用String。Kotlin的类型推断方法为您提供了简洁性和类型安全性。

空安全

在某些语言中,可以在不提供初始显式值的情况下声明引用类型变量。在这些情况下,变量通常包含空值。默认情况下,Kotlin变量不能包含空值。这意味着以下代码段无效:

// Fails to compile
val languageName: String = null

要使变量具有空值,它必须是可空类型。可以通过在变量的类型后缀来将变量指定为可空值?,如以下示例所示:

// Fails to compile
val languageName: String? = null

随着String?类型,你可以指定无论是String价值还是null到 languageName。

您必须谨慎处理可为空的变量,否则可能会造成可怕的后果 NullPointerException。例如,在Java中,如果尝试对空值调用方法,则程序将崩溃。

Kotlin提供了许多机制来安全处理可为空的变量。有关更多信息,请参阅 Android中的常见Kotlin模式:Nullability

有条件的

Kotlin具有几种用于实现条件逻辑的机制。其中最常见的是if-else语句。如果在if关键字旁边用括号括起来的表达式的计算结果为true,则执行该分支内的代码(即紧接在花括号中的紧跟其后的代码)。否则,将else执行分支内的代码。

if (count == 42) {
    println("I have the answer.")
} else {
    println("The answer eludes me.")
}

您可以使用表示多个条件else if。这使您可以在单个条件语句中表示更精细,更复杂的逻辑,如以下示例所示:

if (count == 42) {
    println("I have the answer.")
} else if (count > 35) {
    println("The answer is close.")
} else {
    println("The answer eludes me.")
}

条件语句对于表示状态逻辑很有用,但是您可能会发现编写它们时会重复自己。在上面的示例中,您只需String在每个分支中打印一个。为了避免这种重复,Kotlin提供了 条件表达式。最后一个示例可以重写如下:

val answerString: String = if (count == 42) {
    "I have the answer."
} else if (count > 35) {
    "The answer is close."
} else {
    "The answer eludes me."
}

println(answerString)

隐式地,每个条件分支在其最后一行返回表达式的结果,因此您不需要使用return关键字。因为所有三个分支的结果都是type String,所以if-else表达式的结果也是type String。在此示例中,answerString从if-else表达式的结果中分配了一个初始值。类型推断可用于省略的显式类型声明answerString,但为清楚起见通常将其包括在内是一个好主意。

注意:Kotlin不包括传统的 三元运算符,而是倾向于使用条件表达式。

随着条件语句的复杂性增加,您可以考虑将if-else表达式替换为when表达式,如以下示例所示:

val answerString = when {
    count == 42 -> "I have the answer."
    count > 35 -> "The answer is close."
    else -> "The answer eludes me."
}

println(answerString)

when表达式中的每个分支均由条件,箭头(->)和结果表示。如果箭头左侧的条件求值为true,则返回右侧表达式的结果。请注意,执行不会从一个分支到下一个分支。when表达式示例中的代码在功能上与先前示例中的代码等效,但是可以说更易于阅读。

Kotlin的条件突出了其更强大的功能之一,即 智能铸造。您可以使用条件语句来检查变量是否包含对空值的引用,而不是使用安全调用运算符或非空断言运算符来处理可空值,如以下示例所示:

val languageName: String? = null
if (languageName != null) {
    // No need to write languageName?.toUpperCase()
    println(languageName.toUpperCase())
}

在条件分支内,languageName可以视为不可为空。Kotlin足够聪明,可以认识到执行分支的条件是languageName不包含null值,因此您不必languageName在该分支内将其 视为可为空。这种智能转换适用于null检查, 类型检查或任何满足合同的条件 。

功能

您可以将一个或多个表达式分组为一个函数。您可以将表达式包装在一个函数中,然后调用该函数,而不是每次需要结果时都重复相同的一系列表达式。

要声明一个函数,请使用fun关键字,后跟函数名称。接下来,定义函数采用的输入类型(如果有),并声明其返回的输出类型。函数的主体是定义调用函数时要调用的表达式的地方。

在前面的示例的基础上,以下是完整的Kotlin函数:

fun generateAnswerString(): String {
    val answerString = if (count == 42) {
        "I have the answer."
    } else {
        "The answer eludes me"
    }

    return answerString
}

上面示例中的函数具有名称generateAnswerString。它不需要任何输入。输出类型为的结果String。要调用函数,请使用其名称,后跟调用运算符(())。在下面的示例中,answerString变量使用的结果初始化 generateAnswerString()。

val answerString = generateAnswerString()

函数可以将参数作为输入,如以下示例所示:

fun generateAnswerString(countThreshold: Int): String {
    val answerString = if (count > countThreshold) {
        "I have the answer."
    } else {
        "The answer eludes me."
    }

    return answerString
}

声明函数时,可以指定任意数量的参数及其类型。在上面的示例中,generateAnswerString()采用一个名为countThresholdtype的参数 Int。在函数内,您可以使用参数名称来引用该参数。

调用此函数时,必须在函数调用的括号内包含一个参数:

val answerString = generateAnswerString(42)

简化函数声明

generateAnswerString()是一个相当简单的功能。该函数声明一个变量,然后立即返回。从函数返回单个表达式的结果时,可以通过直接返回函数中包含的if-else表达式的结果来跳过声明局部变量的步骤,如以下示例所示:

fun generateAnswerString(countThreshold: Int): String {
    return if (count > countThreshold) {
        "I have the answer."
    } else {
        "The answer eludes me."
    }
}

您还可以使用赋值运算符替换return关键字:

fun generateAnswerString(countThreshold: Int): String = if (count > countThreshold) {
        "I have the answer"
    } else {
        "The answer eludes me"
    }

匿名功能

并非每个函数都需要一个名称。某些功能可以通过其输入和输出来直接识别。这些功能称为匿名功能。您可以保留对匿名函数的引用,以后使用该引用来调用匿名函数。您还可以像其他引用类型一样在应用程序中传递引用。

val stringLengthFunc: (String) -> Int = { input ->
    input.length
}

val stringLength: Int = stringLengthFunc("Android")

高阶函数

一个函数可以将另一个函数作为参数。将其他函数用作参数的函数称为高阶函数。该模式对于组件之间的通信很有用,就像您在Java中使用回调接口一样。

这是一个高阶函数的示例:

fun stringMapper(str: String, mapper: (String) -> Int): Int {
    // Invoke function
    return mapper(str)
}

该stringMapper()函数String与一个函数一起使用,该函数Int从String传递给它的a 派生一个值。

您可以stringMapper()通过传递String和来满足其他输入参数的函数进行调用,即,将a String作为输入并输出an 的函数Int,如以下示例所示:

stringMapper("Android", { input ->
    input.length
})

如果匿名函数是函数上定义的最后一个参数,则可以将其传递到用于调用该函数的括号之外,如以下示例所示:

stringMapper("Android") { input ->
    input.length
}

在整个Kotlin标准库中都可以找到匿名函数。有关更多信息,请参见 高阶函数和Lambda

到目前为止提到的所有类型都内置在Kotlin编程语言中。如果要添加自己的自定义类型,则可以使用class关键字定义一个类,如以下示例所示

class Car

属性

类使用属性表示状态。一个 属性是类级的变量,其可以包括getter,setter,和一个backing字段。由于汽车需要车轮来驱动,因此您可以将Wheel对象列表添加为的属性Car,如以下示例所示:

class Car {
    val wheels = listOf<Wheel>()
}

请注意,它wheels是一个public val,表示wheels可以从Car类外部访问,并且不能重新分配。如果要获取的实例Car,则必须首先调用其构造函数。从那里,您可以访问其任何可访问的属性。

val car = Car() // construct a Car
val wheels = car.wheels // retrieve the wheels value from the Car

如果要自定义轮子,则可以定义一个自定义构造函数,该构造函数指定如何初始化类属性:

class Car(val wheels: List<Wheel>)

在上面的示例中,类构造函数将a List作为构造函数参数,并使用该参数初始化其wheels 属性。

类函数和封装

类使用函数对行为进行建模。函数可以修改状态,从而帮助您仅公开希望公开的数据。此访问控制是称为封装的更大的面向对象概念的一部分。

在下面的示例中,该doorLock属性对Car类外部的任何内容保持私有。要解锁汽车,必须调用unlockDoor() 传递有效键的函数,如以下示例所示:

class Car(val wheels: List<Wheel>) {

    private val doorLock: DoorLock = ...

    fun unlockDoor(key: Key): Boolean {
        // Return true if key is valid for door lock, false otherwise
    }
}

如果要自定义如何引用属性,则可以提供自定义的getter和setter。例如,如果您想在限制访问属性设置器的同时公开属性的getter,则可以将该属性指定为 private:

class Car(val wheels: List<Wheel>) {

    private val doorLock: DoorLock = ...

    val gallonsOfFuelInTank: Int = 15
        private set

    fun unlockDoor(key: Key): Boolean {
        // Return true if key is valid for door lock, false otherwise
    }
}

通过属性和函数的组合,可以创建对所有类型的对象建模的类。

互通性

Kotlin最重要的功能之一是它与Java的流畅互操作性。由于Kotlin代码可以编译为JVM字节码,因此您的Kotlin代码可以直接调用Java代码,反之亦然。这意味着您可以直接从Kotlin利用现有的Java库。此外,大多数Android API都是用Java编写的,您可以直接从Kotlin对其进行调用。

Kotlin是一种灵活,实用的语言,具有越来越多的支持和动力。如果您还没有尝试,我们鼓励您尝试一下。接下来,请查看Kotlin官方文档 以及有关如何在Android应用中应用常见Kotlin模式的指南 。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值