【问题标题】:Kotlin: difference between IT and THIS keywordKotlin:IT 和 THIS 关键字之间的区别
【发布时间】:2020-03-02 08:57:21
【问题描述】:

在一次 kotlin 采访中,有人问我 itthis 关键字之间的区别。

我在 google 上进行了搜索,但无法找到问题的正确答案。

谁能指导我这两者之间的实际区别是什么?

我知道这是一个非常基本的问题,我是 kotlin 的新手。

【问题讨论】:

    标签: android kotlin


    【解决方案1】:

    你需要了解Scope Functions

    Kotlin 标准库包含几个函数,它们唯一的 目的是在对象的上下文中执行代码块。 当您在具有 lambda 表达式的对象上调用此类函数时 提供,它形成一个临时范围。

    在这个范围内有一个Context 对象,可以是thisit

    在作用域函数runapplywith 中,作用域(暂时)更改为您正在调用此函数的对象的作用域:

    val str = "Hello"
    str.run {
        //Here this refers to str
    }
    

    在作用域函数letalso 中,作用域没有改变(与调用者作用域相同),但您的 lambda 将在 lambda 内接收到 it 的上下文:

    val str = "Hello"
    str.let {
        //Here it refers to str
    }
    

    您可以查看链接以获取更多信息。

    【讨论】:

    • 感谢您提供详细信息。但是为什么我们不能在扩展函数中使用“IT”呢?我们需要在扩展函数中使用“THIS”。
    • @HarshShah 因为扩展函数有一个接收器类型。你可以在这里阅读:stackoverflow.com/a/45875492/2757664
    • 你能写出显示使用差异的代码吗?因为我不明白你为什么放几乎相同的代码示例。
    • @SalimMazariBoufares thisit 关键字的区别基本上是这个(在问题中被问到)。但是,每个作用域函数之间存在细微差别,这完全取决于您的用例。我建议阅读此链接:kotlinlang.org/docs/scope-functions.html#function-selection
    • @SaeedEntezari 好吧,谢谢您的回答,但这不是我的问题,您实际上放了两个相似的代码以显示某种差异,但是在这一点上,两者之间的使用没有区别跑,让。一个最小的例子可能是: val str = "Hello"; str.let { it.length }; str.run { 长度 }
    【解决方案2】:

    it 仅在具有单个参数的 lambda 内部相关。它是单个参数的默认名称,并且是允许您省略命名单个参数的简写。以这种方式声明的函数可能如下所示:

    (String) -> Unit
    

    在 lambda 中,this 是接收者参数。仅当函数定义为具有接收器时才有效,如下所示:

    String.() -> Unit
    

    如果函数声明没有接收者,this 的含义与它在 lambda 范围之外的含义相同。对于扩展函数,它是扩展函数的接收者。否则,它是包含该函数的类。

    【讨论】:

      【解决方案3】:

      itthis 关键字之间的区别可以通过 lambda 方法接收器(也称为高阶函数)的示例来解释

      假设您已经编写了一个函数或使用了一个为您提供回调的函数作为 lambda 方法接收器。像这样:() -> Unit

      因此,您希望回调的方式有两种可能性:

      1. 为回调提供参数

        • 回调参数意味着你想给你的回调一个参数,调用者可以在调用时使用,也被认为是

      上面写的只是意味着:(Int) -> Unit。这个函数式方法参数可以在调用时给你整数。

      查看下面的 sn-p:

      fun someMethodWithCallback(callback: (Int) -> Unit) {
          callback(0)
      }
      
      // On the time of consumption, the `Int` parameter by default exposed to callback as it parameter.
      obj.someMethodWithCallback { it -> // Here it is the method parameter of callback that we passed, you can also rename it to any other named value
          // it can be directly used as Int value if needed or you can rename it at receiver above
      }
      

      注意:您可以为回调提供多个参数,然后您将无法接收 ,而回调会为您提供传递的变量数量。

      1. 为回调提供对象

        • 提供回调的另一种方法是提供对象本身作为回调参数。这意味着回调语法略有变化,并将对象本身作为回调参数 this

      上面写的只是意味着:Int.() -> Unit。此功能方法对象可以在调用时为您提供整数。

      查看下面的 sn-p:

      fun someMethodWithCallback(callback: Int.() -> Unit) {
          callback(0)
      }
      
      // On the time of consumption, the `Int` parameter by default exposed to callback as it parameter.
      obj.someMethodWithCallback { this // Here this is the method object of callback that we passed, you can not rename it to anything else
          // it can be used as Int value by referencing as this
      }
      

      希望它有意义!

      【讨论】:

      • 感谢您提供详细信息。但是为什么我们不能在扩展功能中使用“IT”呢?我们需要在扩展函数中使用“THIS”。
      【解决方案4】:

      我想在没有花哨的词的情况下进行极端基础。

      it 关键字
      当您有一个参数时,您可以使用 it 调用 关键字,它与 HOF 配合得很好,例如,

       private fun itKeyword(itKeyword:(String) -> Unit) {
              itKeyword("")
          }
      
          fun callItFun() {
              itKeyword {//it:String // this is high light over here like this
      
              }
      

      但是如果你尝试做这样的事情:

      private fun itKeyword(itKeyword:(String, Int) -> Unit) {
              itKeyword("", 1)
          }
      
          fun callItFun() {
              itKeyword {yourName, age -> //yourName, age is define by user
              }
         }
      

      看到了吗?编译器在这里没有 it 关键字定义,但是当我们定义 HOF 时,我们必须传递两个参数,但是如果我们保持这个为空,编译器会给我们错误 嘿,传递一些东西,老兄,我别说什么变量这里有两个变量传递过来。
      这意味着,当您只有一个参数时,您可以使用 it 关键字来调用它。

      这个关键字
      有两个范围或变量/属性全局和局部范围,当您将某个变量定义为全局范围并且您想在多个方法/函数中调用它并且在某个地方您必须使用相同类型的另一个具有相同名称的变量时在本地范围内,在这种情况下,我们将使用 this 关键字,为什么会这样?

      private lateinit var mContext: Context
      
          fun thisKeyword(mContext: Context) {
              this.mContext = mContext
          }
      

      但是如果我们不使用 this 关键字并保持这样的状态:

      private lateinit var mContext: Context
          fun thisKeyword(mContext: Context) {
              mContext = mContext
          }
      

      编译器会说,伙计,你做了什么,我脑子里没有敲响警钟 JK,编译器会说,Val 无法重新分配,等等?我们没有将它初始化为 val 但如果我们在全局范围内看到我们将它初始化为 var 但你猜怎么着?编译是对的。在 Kotlin 当将某些东西传递给函数参数时,它们默认充当 Val 这意味着没有 this 编译器使用的是局部范围变量而不是全局范围,但是当我们使用 this 关键字我们告诉编译器,这里的关键字 this 属性在 = 之前是全局范围 this.mContext 而 = 之后是本地范围,所以这就是我们使用 this 关键字避免变量冲突。

      我希望这会有所帮助,thankYou()。

      【讨论】:

        【解决方案5】:

        如果这对某人有帮助:

        with scope like : run, apply, with, 来调用对象的方法,我们可以直接调用它们,因为它具有对象的范围。换句话说,run-block 具有“this”范围。

        private fun methodWithRun() {
        
            val dummy = Dummy()
            dummy.run {
                this.dummyFun()
                this.dummyVar = "10"
            }
            
        }
        

        虽然像 :let 这样的作用域也可以调用对象的方法,但我们可以使用“it”来调用它们,因为它具有编写此方法的类 win 的作用域。

        private fun methodWithLet() {
            
            val dummy = Dummy()
            dummy.let {
                it.dummyFun()
                it.dummyVar = "10";
            }
            
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-08-24
          • 2013-10-23
          • 2019-01-17
          • 1970-01-01
          • 2011-04-30
          • 2012-08-18
          • 1970-01-01
          • 2017-12-22
          相关资源
          最近更新 更多