7

I'm trying to assign a callback implementation of an interface (defined inside a class A) to a variabile defined inside another class B. Let's say that class A has the interface OnSomethingHappens which defines a doSomething method.

Inside class B I've defined my callback variable like this:

private lateinit var callback:A.OnSomethingHappens

I need to create an instance of class A passing callback variabile to the constructor in this way:

myinstanceA = A(callback)

I'm trying to assign an instance of an anonymous class that implements A.OnSomethingHappens using this code:

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

but the compiler says "expecting member declaration" for my callback variable and "name expected" for object. What I'm doing wrong?

Instead, I'm able to define and at the same time assign the callback variable in this way:

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

Why? Which are the differences and a possible solution?

user9257465
  • 91
  • 1
  • 1
  • 6
  • I try to add more details so you could understand better.I'm using the line of code I write above in my Android application and class B for me is a Fragment and class A is a public class with some method I use from fragment in order to do some work for me. When class A ends this work use the callback I passed inside its constructor (when I create an instance of class A inside fragment), to call the method doSomethig() defined inside the interface OnSomethingHappens. The fragment implements this method and prepare the callback variable as I show above, and pass it to class A. – user9257465 Mar 27 '18 at 11:33

3 Answers3

2

I'm trying to assign an instance of an anonymous class that implements A.OnSomethingHappens using this code: ...

This should work, but only inside a method:

class B {
    private lateinit var callback:A.OnSomethingHappens

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

Given the error message and that private var compiles (which doesn't inside a method), you are trying to set it directly in the body of the class instead:

class B {
    private lateinit var callback:A.OnSomethingHappens

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

This is illegal: the only code you can write there is member definitions and init blocks.

Also, if you can initialize callback directly where it's defined or inside init, there's no point to lateinit in the first place.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
1

It's not obvious from the code snippets cut down to such small pieces, but your issue is that you're writing down the assignment inside the body of a class, but not inside a function.

Here's an example of a valid declaration and immediate assignment:

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

Here's an example of an invalid assignment, which places an arbitrary expression in the body of a class:

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
}

Instead, you could put this initialization inside a function:

class A {
    lateinit var x: X

    fun initializeX() {
        x = X()
    }
}

Or inside an initializer block (in this case, you don't even need lateinit):

class A {
    var x: X

    init {
        x = X()
    }
}

While I couldn't explain how to solve your exact problem, because I can't quite understand what code is in which class, I hope these examples and explanation helped.

zsmb13
  • 85,752
  • 11
  • 221
  • 226
1

Hmm, let me propose a variant. It's more simple for me:

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())
    }
}

Using Kotlin lambdas. Hope this will help you.

Dmitry Lvov
  • 347
  • 3
  • 9