📜  Kotlin – 作用域函数

📅  最后修改于: 2022-05-13 01:54:54.285000             🧑  作者: Mango

Kotlin – 作用域函数

Kotlin 标准库中有几个函数可以帮助在对象上下文中执行代码块。使用 lambda 表达式在对象上调用这些函数会创建一个临时作用域。这些函数称为作用域函数。我们可以在没有名称的情况下访问这些函数的对象。听起来很混乱!我们来看一个例子,

示例:不使用作用域函数

Kotlin
class Company() {
    lateinit var name: String
    lateinit var objective: String
    lateinit var founder: String
}
  
fun main() {
    // without using scope function
  
    // creating instance of Company Class
    val gfg = Company() 
  
    // initializing members of the class
    gfg.name = "GeeksforGeeks"
    gfg.objective = "A computer science portal for Geeks"
    gfg.founder = "Sandeep Jain"
  
    println(gfg.name)
}


Kotlin
class Company() {
    lateinit var name: String
    lateinit var objective: String
    lateinit var founder: String
}
  
fun main() {
    // using scope function
    val gfg = Company().apply {
        // don't need to use object
        // name to refer members
        name = "GeeksforGeeks"
        objective = "A computer science portal for Geeks"
        founder = "Sandeep Jain"
    }
    println(gfg.name)
}


Kotlin
fun main() {
    // nullable variable a
    // with value as null
    var a: Int? = null
    // using let function
    a?.let {
        // statement(s) will
        // not execute as a is null
        print(it)
    }
    // re-initializing value of a to 2
    a = 2
    a?.let {
        // statement(s) will execute
        // as a is not null
        print(a)
    }
}


Kotlin
class Company() {
    lateinit var name: String
    lateinit var objective: String
    lateinit var founder: String
}
  
fun main() {
    Company().apply {
        // same as founder = “Sandeep Jain”
        this.founder = "Sandeep Jain" 
        name = "GeeksforGeeks"
        objective = "A computer science portal for Geeks"
    }
}


Kotlin
class Company() {
    lateinit var name: String
    lateinit var objective: String
    lateinit var founder: String
}
  
fun main() {
    val gfg = Company().apply {
        name = "GeeksforGeeks"
        objective = "A computer science portal for Geeks"
        founder = "Sandeep Jain"
    }
  
    // with function
    with(gfg) {
        // similar to println( "${this.name}" )
        println(" $name ")
    }
}


Kotlin
class Company() {
    lateinit var name: String
    lateinit var objective: String
    lateinit var founder: String
}
  
fun main(args: Array) {
    println("Company Name : ")
    var company: Company? = null
    // body only executes if 
    // company is non-null
    company?.run {     
        print(name)
    }
    print("Company Name : ")
    // re-initialize company
    company = Company().apply {
        name = "GeeksforGeeks"
        founder = "Sandeep Jain"
        objective = "A computer science portal for Geeks"
    }
    // body executes as 
    // 'company' is non-null
    company?.run {     
        print(name)
    }
}


Kotlin
fun main() {
    // initialized
    val list = mutableListOf(1, 2, 3)
  
    // later if we want to perform 
    // multiple operations on this list
    list.also {
        it.add(4)
        it.remove(2)
        // more operations if needed
    }
    println(list)
}


Kotlin
Company().apply {
   // same as : name = "GeeksforGeeks"
   this.name = "GeeksforGeeks"   
   this.founder = "Sandeep Jain"
   this.objective = "A computer science portal for Geeks" 
}


Kotlin
Company().let {
   it.name = "GeeksforGeeks"
   it.founder = "Sandeep Jain"
   it.objective = "A computer science portal for Geeks"
}


Kotlin
class Company {
    var name: String = "GeeksforGeeks"
    var founder: String = "Sandeep Jain"
    var objective: String = "A computer science portal for Geeks"
}
  
fun main() {
    val founderName: String = with(Company()) {
        // 'founder' is returned by 'with' function
        founder    
    }
    println("GfG's Founder : $founderName")
}


Kotlin
class Company {
    var name: String = "GeeksforGeeks"
    var founder: String = "Sandeep Jain"
    var objective: String = "A computer science portal for Geeks"
}
  
fun main() {
    val gfg = Company().apply {
        // any statement(s)
    }
    // gfg is an object of class Company as
    // return of apply() is context object
    print("GfG's Founder : ${gfg.founder}");
}


输出:

GeeksforGeeks

示例:使用范围函数



科特林

class Company() {
    lateinit var name: String
    lateinit var objective: String
    lateinit var founder: String
}
  
fun main() {
    // using scope function
    val gfg = Company().apply {
        // don't need to use object
        // name to refer members
        name = "GeeksforGeeks"
        objective = "A computer science portal for Geeks"
        founder = "Sandeep Jain"
    }
    println(gfg.name)
}

输出:

GeeksforGeeks

解释

你一定注意到了,当我们不使用作用域函数的时候,每次都需要写对象名来引用类的成员。使用作用域函数时,我们可以直接引用成员,而无需对象名称。这是使用 scope函数的方法之一。我们将在本文中详细了解它们。

作用域函数

每个作用域函数都有明确定义的用例,尽管它们都有几乎相同的结果。现在让我们看看每个作用域函数及其用例:

作用域函数的应用

作用域函数使代码更加清晰可读简洁,这是 Kotlin 语言的主要特点。

作用域函数的类型

作用域函数有五种类型:

  1. 申请

这些功能中的每一个在本质上都非常相似,只有细微的差别。决定使用哪个函数以及何时使用常常令人困惑。因此,我们需要知道这些功能及其用例之间有什么区别。

这些功能的区别:



这些功能主要有两个区别:

  1. 引用上下文对象的方式(即使用“this”或“it”关键字)
  2. 返回值(即返回“上下文对象”或“lambda 结果”)

范围函数表:

Function

Object Reference

Return Value

let

it

Lambda result

run



this

Lambda result

with

this

Lambda result

apply

this

Context object

also

it

Context object

1.让函数

Context object  :   it 
Return value    :   lambda result

用例:

let函数通常用于提供空安全调用。将安全调用运算符(?.)与 'let' 一起使用以确保空值安全。它仅使用非空值执行块。

例子:

科特林

fun main() {
    // nullable variable a
    // with value as null
    var a: Int? = null
    // using let function
    a?.let {
        // statement(s) will
        // not execute as a is null
        print(it)
    }
    // re-initializing value of a to 2
    a = 2
    a?.let {
        // statement(s) will execute
        // as a is not null
        print(a)
    }
}

输出:

2

解释:

如您所见,当 'a' 的值为 'null' 时,让函数简单地避开代码块。因此,解决了程序员最大的噩梦——NullPointerException。

2. 应用函数

Context object   :    this
Return value     :    context object

用例:

顾名思义——“将这些应用于对象”。它可用于对接收器对象的成员进行操作,主要用于初始化成员。



例子:

科特林

class Company() {
    lateinit var name: String
    lateinit var objective: String
    lateinit var founder: String
}
  
fun main() {
    Company().apply {
        // same as founder = “Sandeep Jain”
        this.founder = "Sandeep Jain" 
        name = "GeeksforGeeks"
        objective = "A computer science portal for Geeks"
    }
}

3.带函数

Context object  :   this
Return value    :   lambda result

用例:

推荐使用 'with' 在上下文对象上调用函数而不提供 lambda 结果。

例子:

科特林

class Company() {
    lateinit var name: String
    lateinit var objective: String
    lateinit var founder: String
}
  
fun main() {
    val gfg = Company().apply {
        name = "GeeksforGeeks"
        objective = "A computer science portal for Geeks"
        founder = "Sandeep Jain"
    }
  
    // with function
    with(gfg) {
        // similar to println( "${this.name}" )
        println(" $name ")
    }
}

输出:

GeeksforGeeks

4.运行函数

Context object   :    this
Return value     :    lambda result

'run'函数可以说是 'let' 和 'with' 函数的组合。

用例:

当对象 lambda 包含初始化和返回值的计算时使用。使用 run 我们可以执行空安全调用以及其他计算。



例子:

科特林

class Company() {
    lateinit var name: String
    lateinit var objective: String
    lateinit var founder: String
}
  
fun main(args: Array) {
    println("Company Name : ")
    var company: Company? = null
    // body only executes if 
    // company is non-null
    company?.run {     
        print(name)
    }
    print("Company Name : ")
    // re-initialize company
    company = Company().apply {
        name = "GeeksforGeeks"
        founder = "Sandeep Jain"
        objective = "A computer science portal for Geeks"
    }
    // body executes as 
    // 'company' is non-null
    company?.run {     
        print(name)
    }
}

输出:

Company Name : 

Company Name : GeeksforGeeks

解释:

当 'company' 值为 null 时,运行的主体将被简单地忽略。当它为非空时,主体执行。

5.还有函数

Context object   :    it
Return value     :    context object

用例:

当我们初始化对象成员时,它用于我们必须执行附加操作的地方。

例子:

科特林

fun main() {
    // initialized
    val list = mutableListOf(1, 2, 3)
  
    // later if we want to perform 
    // multiple operations on this list
    list.also {
        it.add(4)
        it.remove(2)
        // more operations if needed
    }
    println(list)
}

输出:



[1, 3, 4]

对象引用

作用域函数中有两种对象引用方式:

1.这个

我们可以通过 lambda 接收器关键字this来引用上下文对象。 this关键字在'run'、'with' 和 'apply'函数中执行对象引用。

例子:

科特林

Company().apply {
   // same as : name = "GeeksforGeeks"
   this.name = "GeeksforGeeks"   
   this.founder = "Sandeep Jain"
   this.objective = "A computer science portal for Geeks" 
}

2.它

'let' 和 'also' 函数将对象的上下文称为lambda 参数。

例子:

科特林



Company().let {
   it.name = "GeeksforGeeks"
   it.founder = "Sandeep Jain"
   it.objective = "A computer science portal for Geeks"
}

返回值

作用域函数可以返回两种类型的返回值:

1. Lambda 结果

如果我们在代码块的末尾写任何表达式,它就会成为作用域函数的返回值。 'let'、'run' 和 'with' 函数的返回值是 lambda 结果。

例子:

科特林

class Company {
    var name: String = "GeeksforGeeks"
    var founder: String = "Sandeep Jain"
    var objective: String = "A computer science portal for Geeks"
}
  
fun main() {
    val founderName: String = with(Company()) {
        // 'founder' is returned by 'with' function
        founder    
    }
    println("GfG's Founder : $founderName")
}

输出:

GfG's Founder : Sandeep Jain

2. 上下文对象

'apply' 和 'also' 函数返回上下文对象本身。在这种情况下,我们不需要指定返回值。上下文对象会自动返回。

例子:

科特林

class Company {
    var name: String = "GeeksforGeeks"
    var founder: String = "Sandeep Jain"
    var objective: String = "A computer science portal for Geeks"
}
  
fun main() {
    val gfg = Company().apply {
        // any statement(s)
    }
    // gfg is an object of class Company as
    // return of apply() is context object
    print("GfG's Founder : ${gfg.founder}");
}

输出:

GfG's Founder : Sandeep Jain

概括

  • 作用域函数使代码更具可读性、清晰和简洁。
  • 对象引用——“this”和“it”。
  • 返回值——上下文对象和 lambda 结果。
  • let :使用可为空的对象来避免 NullPointerException。
  • apply :更改对象配置。
  • run:对可为空的对象进行操作,执行 lambda 表达式。
  • 也:添加额外的操作。
  • with :对非空对象进行操作。