最近在Kotlin代码中,我经常看到这样的写法:

interface Person {
  fun saySomething()
}
​
class Adult: Person {
  var name = ""
  override fun saySomething() {
    println("Hello world!")
   }
​
  fun weirdSay(block: Person.() -> Unit) {
    println("包装一下")
    this.block()
   }
  private fun sayMore() {
    println("私有办法")
   }
  fun answer(question: String) {
    println("$question 的答案")
   }
}
​
fun main() {
  val adult = Adult()
  adult.weirdSay {
    saySomething()
//     sayMore() 无法找到私有办法//     answer("问题") 无法找到
   }
}

输出为

包装一下
Hello world!

注意看main函数,这里调用了adult的weirdSay,传入一个lambda表达式,传入的居然是adult自己的saySomething,那是因为block: Person.() -> Unit语法

() -> Unit是Kotlin界说不接纳任何参数并且不回来任何东西的函数的方式。

并且有一种办法能够指定该函数将在何处被调用,因此有了Person.()部分。

一个参数类型为 Person.() -> Unit 的 Lambda 表达式,它能够拜访和修正 Person 类型的特点和办法,具体意义是:为“给我一个在Person上调用的块。它必须不接纳任何参数,并且不回来任何东西。”

显然,这是一种界说即时扩展函数的方式。这允许你界说在类内部运行可是从类外部界说的函数。

也就是说,当咱们需求在事务中用到某个类内部的办法时,咱们能够给这个类内部添加一个类似于 fun weirdSay(block: Person.() -> Unit) {的办法,对需求调用的办法进行相应的处理,然后在外面直接调用weirdSay就行了,一起,在外部也能够拜访或许修正特点

class Person(var name: String) {
  fun say() {
    println("My name is $name")
   }
  fun weirdSay(block: Person.() -> Unit) {
    println("包装一下")
    block()
   }
}
​
​
fun main() {
  val person = Person("Tom")
  person.weirdSay {
    name = "Jerry"
    say()
   }
}

输出为

包装一下
My name is Jerry

这姿态,大都情况下,就能够在这一扩展函数中自在的像在person类中调用自己一样,比如

interface Person {
  fun saySomething()
  fun sayMore() 
}
class Adult: Person {
  override fun saySomething() {
    println("Hello world!")
   }
​
  fun weirdSay(block: Person.() -> Unit) {
    println("包装一下")
    this.block()
   }
  override fun sayMore() {
    println("sayMore")
   }
​
}
​
fun main() {
  val adult = Adult()
  adult.weirdSay {
    saySomething()
    sayMore()
   }
}

添加一个sayMore办法,也能够持续调用,weirdSay{}内部就像person的内部一样(除了private不能拜访)

学习到了小技巧,就赶紧用到项目中吧!