0

In some Fragments and other classes (in Java) I have a public interface ISomeActions with functions that I then call from some other parts in that class, to denote actions. So, I have a ISomeListener listener that I set in the constructor, or right after I create an object of SomeClass. How can I achieve this in Kotlin?

Example:

public class SomeClass{
    public ISomeListener listener;
    public interface ISomeListener{
       public void doSomething();
    }

    void actuallyDoSomething(){
        listener.doSomething();
    }
}

I think I can use a lateinit var listener : SomeListener, but I don't know if that would be adequate. The member is an Interface, and not an implementation of that Interface in case it's called after the Activity finishes.

1 Answers1

0

1) Constructor

class MyClass(private val myInterface: MyInterface) { ... }

This way myInterface is immutable. You can be sure that this will never be null.

2) After object creation - null

class MyClass(var myInterface: MyInterface? = null) { ... }

Now myInterface is mutable and can be null at any time. You can safety access it via myInterface?.someMethod() (is myInterface is null call won't be invoked). To access and assign listener use myClassInstance.myInterface = myInterfaceInstance.

Because of default param you can create your class with or without constructor param:

val myClass1 = MyClass()
val myClass2 = MyClass(interfaceInstanceOrNull)

3) After object creation - lateinit

class MyClass(myInterface: MyInterface? = null) {
    lateinit var _myInterface: MyInterface
    init {
        if (myInterface != null) { _myInterface = myInterface }
    }
}

In my opinion the worst solution. lateinit is designed for injecting field after creation, for DI frameworks like dagger. If you try call method on myInterface if it is not init yet UninitializedPropertyAccessException will be thrown. You can check if property is initlialized like this:

if (::_myProperty.isInitialized) { _myProperty.doSth() }

In my opinion you should use the first or the second approach. As I understand you cannot always init object with instance of MyInterface, so the second one seems legit for your puroposes.

Cililing
  • 4,303
  • 1
  • 17
  • 35
  • Thanks, that's exactly what I needed to clarify! I think I'll use the second approach. – Camilink94 Apr 01 '19 at 23:11
  • If MyClass is a Fragment in Android, where non-default constructors are supposed to be avoided, is it better to pass it in the arguments, or as a nullable property of the fragment? – Camilink94 Apr 04 '19 at 05:23
  • Actually you should use `newInstance` pattern (static method creating fragment and applying bundle to new fragment). See this for example: https://stackoverflow.com/a/9245510/7508302 – Cililing Apr 04 '19 at 07:27