kotlin function: run with let also apply

Scoping functions (作用域 函数)

提供了一个 内部独立的区间(也就是方法的上下文 如下的run方法)

  • run{} 提供独立上下文
  • with(T){} 上下文为参数
  • T.run{} 对比with(T) T.run{}是个拓展方法 extension function,默认参数是T. 就是T相当于方法内部(作用域内)的this
  • T.let{} 默认参数是T 就是T相当于lambda的参数
  • T.also{} return值在链式调用中一直为T
  • T.apply{}
run
fun test() {
    var mood = "I am sad"

    run {
        val mood = "I am happy"
        println(mood) // I am happy
    }

    println(mood)  // I am sad
}
  • Scope
    如上 run内部是一个区间mode,外部是另一个区间。所以mode使用的是run内部的
  • return value
    run {
        if (firstTimeView) introView else normalView
    }.show()
scope function 3个属性

从这三个属性的维度 来对上述方法,再次划分
1. Normal vs. extension function

//normal function
with(webview.settings) {
    javaScriptEnabled = true
    databaseEnabled = true
}
// similarly function
// extension function
webview.settings.run {
    javaScriptEnabled = true
    databaseEnabled = true
}

好处 webview.settings 可能为null,所以安全的写法:

// Yack!
with(webview.settings) {
      this?.javaScriptEnabled = true
      this?.databaseEnabled = true
   }
}
// Nice.
webview.settings?.run {
    javaScriptEnabled = true
    databaseEnabled = true
}
  1. This vs. it argument

T.run和T.let只有一点不同 他们接受的参数

stringVariable?.run {
      println("The length of this String is $length")
}
// Similarly.
stringVariable?.let {
      println("The length of this String is ${it.length}")
}

看方法的signature(方法签名,包括方法参数列表),发现T.run是一个扩展方法block: T.() 所以在scope内T是被当做this,方法中this可以被省略,所以$length 等价于${this.length}

T.let方法的signature是block: (T) 像lambda表达式一样,这里我们成为 it 参数

另外it也是可以改名的:

stringVariable?.let {
      nonNullString ->
      println("The non null string is $nonNullString")
}
  1. Return this vs. other type

T.let and T.also

val original = "abc"

// Evolve the value and send to the next chain
original.let {
    println("The original String is $it") // "abc"
    it.reversed() // evolve it as parameter to send to next let
}.let {
    println("The reverse String is $it") // "cba"
    it.length  // can be evolve to other type
}.let {
    println("The length of the String is $it") // 3
}

// Wrong
// Same value is sent in the chain (printed answer is wrong)
original.also {
    println("The original String is $it") // "abc"
    it.reversed() // even if we evolve it, it is useless
}.also {
    println("The reverse String is ${it}") // "abc"
    it.length  // even if we evolve it, it is useless
}.also {
    println("The length of the String is ${it}") // "abc"
}

// Corrected for also (i.e. manipulate as original string
// Same value is sent in the chain 
original.also {
    println("The original String is $it") // "abc"
}.also {
    println("The reverse String is ${it.reversed()}") // "cba"
}.also {
    println("The length of the String is ${it.length}") // 3
}

let return的是这次调用的结果,also return的仍旧是调用方

also看起来没用,可以整合到一个方法,但是也有好处:
1. It can provide a very clear separation process on the same objects i.e. making smaller functional section. (更细粒度的分割代码、逻辑)
2. It can be very powerful for self manipulation before being used, making a chaining builder operation.(有利于build模式)

结合使用
// Normal approach
fun makeDir(path: String): File  {
    val result = File(path)
    result.mkdirs()
    return result
}
// Improved approach
fun makeDir(path: String) = path.let{ File(it) }.also{ it.mkdirs() }
另外T.apply
  1. It is an extension function
  2. It send this as it’s argument.
  3. It returns this (i.e. itself)

上面说的this实际就是T

// Normal approach
fun createInstance(args: Bundle) : MyFragment {
    val fragment = MyFragment()
    fragment.arguments = args
    return fragment
}
// Improved approach
fun createInstance(args: Bundle) 
              = MyFragment().apply { arguments = args }

非链式的做成链式调用

// Normal approach
fun createIntent(intentData: String, intentAction: String): Intent {
    val intent = Intent()
    intent.action = intentAction
    intent.data=Uri.parse(intentData)
    return intent
}
// Improved approach, chaining
fun createIntent(intentData: String, intentAction: String) =
        Intent().apply { action = intentAction }
                .apply { data = Uri.parse(intentData) }
方法的选择

方法的选择

原文: Mastering Kotlin standard functions: run, with, let, also and apply

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
牙科就诊管理系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了用户在线查看数据。管理员管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等功能。牙科就诊管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 管理员在后台主要管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等。 牙医列表页面,此页面提供给管理员的功能有:查看牙医、新增牙医、修改牙医、删除牙医等。公告信息管理页面提供的功能操作有:新增公告,修改公告,删除公告操作。公告类型管理页面显示所有公告类型,在此页面既可以让管理员添加新的公告信息类型,也能对已有的公告类型信息执行编辑更新,失效的公告类型信息也能让管理员快速删除。药品管理页面,此页面提供给管理员的功能有:新增药品,修改药品,删除药品。药品类型管理页面,此页面提供给管理员的功能有:新增药品类型,修改药品类型,删除药品类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值