【问题标题】:Kotlin, how to assign callback implementation to a variableKotlin,如何将回调实现分配给变量
【发布时间】:2018-09-05 17:09:11
【问题描述】:

我正在尝试将接口的回调实现(在类 A 中定义)分配给在另一个类 B 中定义的变量。假设类 A 具有定义 doSomething 方法的接口 OnSomethingHappens。

在 B 类中,我已经这样定义了我的回调变量:

private lateinit var callback:A.OnSomethingHappens

我需要创建一个A类的实例,以这种方式将回调变量传递给构造函数:

myinstanceA = A(callback)

我正在尝试使用此代码分配实现A.OnSomethingHappens 的匿名类的实例:

callback = object : A.OnSomethingHappens {
   override fun doSomething(..){
      //here I put the implementation of this method
   }
 }

但是编译器对我的回调变量说“期望成员声明”,对对象说“期望名称”。 我做错了什么?

相反,我能够以这种方式定义并同时分配回调变量:

private var callback = object : A.OnSomethingHappens {
      override fun doSomething(..){
        //here I put the implementation of this method
      }
    }

为什么?有哪些区别和可能的解决方案?

【问题讨论】:

  • 我尝试添加更多细节,以便您更好地理解。我正在使用我在 Android 应用程序中编写的代码行,B 类对我来说是一个片段,A 类是一个公共类使用我从片段中使用的一些方法来为我做一些工作。当 A 类结束这项工作时,使用我在其构造函数中传递的回调(当我在片段中创建 A 类的实例时),调用在 OnSomethingHappens 接口中定义的方法 doSomethig()。片段实现了这个方法并准备了我上面显示的回调变量,并将其传递给类 A。

标签: kotlin anonymous-inner-class


【解决方案1】:

我正在尝试使用以下代码分配实现 A.OnSomethingHappens 的匿名类的实例:...

这应该有效,但只能在方法内部:

class B {
    private lateinit var callback:A.OnSomethingHappens

    fun someMethod() {
        callback = object : A.OnSomethingHappens { ... }
    }
    ...
}

鉴于错误消息和 private var 编译(不在方法内),您尝试将其直接设置在类的主体中:

class B {
    private lateinit var callback:A.OnSomethingHappens

    callback = object : A.OnSomethingHappens { ... }
    ...
}

这是非法的:您可以编写的唯一代码是成员定义和init 块。

此外,如果您可以直接在定义callback 的位置或在init 内部初始化lateinit,那么首先就没有意义了。

【讨论】:

    【解决方案2】:

    从代码 sn-ps 缩减到如此小的部分并不明显,但您的问题是您在类的主体内写下赋值,而不是在函数内。

    下面是一个有效声明和立即赋值的例子:

    class A {
        var x: X? = X()
    }
    

    这是一个 invalid 赋值示例,它将任意表达式放置在类的主体中:

    class A {
        lateinit var x: X
    
        x = X()        // expression placed inside the class body, invalid syntax
        someFunction() // extra example, calling functions here is invalid in the same way
    }
    

    相反,您可以将此初始化放在一个函数中:

    class A {
        lateinit var x: X
    
        fun initializeX() {
            x = X()
        }
    }
    

    或者在initializer block 内(在这种情况下,您甚至不需要lateinit):

    class A {
        var x: X
    
        init {
            x = X()
        }
    }
    

    虽然我无法解释如何解决您的确切问题,因为我不太明白哪个类中的代码是什么,但我希望这些示例和解释对您有所帮助。

    【讨论】:

      【解决方案3】:

      嗯,让我提出一个变体。对我来说更简单:

      import android.util.Log
      
      class SomeClass {
      
          fun mainMethod() {
      
              ClassWithCallback(
                      { myBackValue: String ->
                          logMyString(myBackValue)
                      }
              )
      
              //simplify
              ClassWithCallback({ logMyString(it) })
          }
      
          private fun logMyString(myBackValue: String) {
              Log.d("SomeClass", myBackValue)
          }
      }
      
      class ClassWithCallback(private val myCallBack: (myBackValue: String) -> Unit) {
      
          init {
              // we do something here and back it by callback
      
              val myString = "Hello! Pass me back!"
              myCallBack.invoke(myString.toUpperCase())
          }
      }
      

      使用Kotlin lambdas。希望这会对你有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-06-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-22
        • 1970-01-01
        • 2014-04-03
        相关资源
        最近更新 更多