第一行代码 第三版 Kotlin部分笔记(3)

仅为个人笔记。

目录

1、字符串内嵌表达式

2、函数的参数默认值

3、标准函数with、run和apply

with函数

run函数

apply函数

4、定义静态方法

单例类

companion object

注解

顶层

5、延迟初始化

6、密封类


1、字符串内嵌表达式


       Kotlin中字符串内嵌表达式的语法规则:

"hello, ${obj.name}. nice to meet you!"

       Kotlin允许我们在字符串里嵌入${}这种语法结构的表达式,并在运行时使用表达式执行的结果替代这一部分内容。
       另外,当表达式中仅有一个变量的时候,还可以将两边的大括号省略:

"hello, $name. nice to meet you!"

2、函数的参数默认值


       具体来讲,我们可以在定义函数的时候给任意参数设定一个默默认值,这样当调用此函数时就不会强制要求调用方为此参数传值,在没有传值的情况下会自动使用参数的默认值。

       这时如果想让num参数使用默认值该怎么办呢?模仿刚才的写法肯定是行不通的,因为编译器会认为我们想把字符串赋值给第一个num参数,从而报类型不匹配的的错误。

       Kotlin提供了另外一种神奇的机制,就是可以通过键值对的方式来传参,从而不必像传统写法那样按照参数定义的顺序来传参。

        我们完全可以通过只编写一个主构造函数,然后给数设定默认值的方式来实现。在给主构造函数的每个参数都设定了默认值之后,我们就可以使用任何传参组合的方式来对Student类进行实例化。

3、标准函数with、run和apply

       Kotlin的标准函数指的是Standard.kt文件中定义的函数,任何Kotlin代码都可以自由地调用所
有的标准函数。

with函数

       with函数接收两个参数:第一个参数可以是一个任意类型的对象,第二个参数是一个Lambda表达式。with函数会在Lambda表达式中提供第一个参数对象的上下文,并使用Lambda表达式中的最后一行代码作为返回值返回。示例代码如下:

 

      with函数可以在连续调用同一个对象的多个方法时让代码变得更加精简。

run函数

       
       首先 run 函数通常不会直接调用, 而是要在某个对象的基础上调用;其次run 函数只接收一个 Lambda 参数,并且会在 Lambda 表达式中提供调用对象的上下文。其他方面和with 函数是一样的,包括也会使用 Lambda 表达式中的最后一行代码作为返回值返回。

apply函数

       apply 函数和 run 函数也是极其类似的,都要在某个对象上调用,并且只接收一个Lambda 参数,也会在 Lambda 表达式中提供调用对象的上下文,但是apply 函数无法指定返回值,而是会自动返回调用对象本身。

 吃水果字符串的打印结果

//run函数
val list = listof("Apple", "Banana", "Orange", "Pear","Grape")
val result = StringBuilder().run {
    append("Start eating fruits.\n")
    for (fruit in list) {
        append(fruit).append("\n")
    }
    append("Ate all fruits.")
    toString()
}
println(result)

4、定义静态方法

       
        静态方法在某些编程语言里面又叫作类方法,指的就是那种不需要创建实例就能调用的方法,所有主流的编程语言都会支持静态方法这个特性。
     

单例类

        像工具类这种功能,在 Kotlin 中就非常推荐使用单例类的方式来实现,比如上述的 Util 工具 类,如果使用Kotlin 来实现的话就可以这样写:
       虽然这里的 doAction() 方法并不是静态方法,但是我们仍然可以使用 Util.doAction() 的方式来调用,这就是单例类所带来的便利性。

companion object

       使用单例类的写法会将整个类中的所有方法全部变成类似于静态方法的调用方式,而如果我们只是希望让类中的某一个方法变成静态方法的调用方式就可以使用刚刚在最佳实践环节用到的companion object 了,示例如下:
       doAction1() 方法是一定要先创建 Util 类的实例才能调用的,而doAction2()方法可以直接使用 Util.doAction2()的方式调用。doAction2()方法其实也并不是静态方法,companion object这个关键字实际上会在Util类的内部创建一个伴生类,而doAction2()方法就是定义在这个伴生类里面的实例方法。只是Kotlin 会保证Util类始终只会存在一个伴生类对象,因此调用Util.doAction2()方法实际上就是调用了Util类中伴生对象的doAction2()方法。
       

注解

       如果你确确实实需要定义真正的静态方法, Kotlin 仍然提供了两种实现方式:注解和顶层方法。
       前面使用的单例类和 companion object 都只是在语法的形式上模仿了静态方法的调用方式,实际上它们都不是真正的静态方法。 如果我们给单例类或companion object 中的方法加上@JvmStatic 注解,那么 Kotlin 编译器就会将这些方法编译成真正的静态方法。
class Util { 

     fun doAction1() { 
        println("do action1") 
     } 

     companion object { 

         //@JvmStatic注解只能加在单例类或companion object中的方法上,如果你尝试加在一个普通方法上,会直接提示语法错误。
         @JvmStatic 
         //doAction2()方法已经成为了真正的静态方法
         fun doAction2() { 
             println("do action2")
         }
    }
}

顶层

       顶层方法指的是那些没有定义在任何类中的方法,比如我们在上一节中编写的main() 方法。 Kotlin 编译器会将所有的顶层方法全部编译成静态方法,因此只要你定义了一个顶层方法,那么它就一定是静态方法。

5、延迟初始化

       如果你的类中存在很多全局变量实例,为了保证它们能够满足 Kotlin 的空指针检查语法标准,你不得不做许多的非空判断保护才行,即使你非常确定它们不会为空。
       延迟初始化使用的是 lateinit 关键字,它可以告诉 Kotlin 编译器,我会在晚些时候对这个变量进行初始化,这样就不用在一开始的时候将它赋值为null了。当你对一个全局变量使用了lateinit关键字时,请一定要确保它在被任何地方调用之前已经完成了初始化工作,否则Kotlin 将无法保证程序的安全性。

::adapter.isInitialized 可用于判断全局 变量是否已经初始化。

6、密封类

       密封类的关键字是 sealed class

     

  由于密封类是一个可继承的类,因此在继承它的时候需要在后面加上一对括号

   

  getResultMsg()方法中的else条件已经不再需要了。这是因为当在when语句中传入一个密封类变量作为条件时,Kotlin 编译器会自动检查该密封类有哪些子类,并强制要求你将每一个子类所对应的条件全部处理。这样就可以保证,即使没有编写else条件,也不可能会出现漏写条件分支的

情况。而如果我们现在新增一个 Unknown 类,并也让它继承自 Result ,此时getResultMsg()方法就一定会报错,必须增加一个 Unknown 的条件分支才能让代码编译通过。

       密封类及其所有子类只能定义在同一个文件的顶层位置,不能嵌套在其他类中,这是被密封类底层的实现机制所限制的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值