1

For example java code

public abstract class BindingElement<T extends ViewDataBinding> {

    T binding;

    abstract public T createBinding(LayoutInflater inflater, ViewGroup parent);

    public BindingElement(ViewGroup parent) {
        binding = createBinding(LayoutInflater.from(parent.getContext()), parent);
        binding.setLifecycleOwner(ViewTreeLifecycleOwner.get(parent));
    }
}

I need some necessary property that defined in constructor. And then i will do something with that property. What is the best way write it in kotlin?

Makc
  • 83
  • 6

3 Answers3

1

This doesn’t directly answer your question but provides a safer alternative.

You should avoid calling an open or abstract function from the constructor in Java or Kotlin, even though it’s allowed. It is fragile and can cause weird bugs that are difficult to resolve. Read here: In Java, is there a legitimate reason to call a non-final method from a class constructor?

An alternative in this case would be to make your function into a constructor parameter. Your class doesn’t even need to be open or abstract to support this.

class ViewBindingParameter<T: ViewBindingData> (
    parent: ViewGroup,
    inflateBinding: (LayoutInflater, ViewGroup)->T
) {

    val binding: T = inflateBinding(LayoutInflater.from(parent.context), parent)

}

Usage:

val bindingParam = ViewBindingParameter(parent, SomeBinding::inflate)

If you aren't planning to add features to this class, you might as well just use a function that directly returns a binding so you don't have to deal with the wrapper class. Maybe an extension function of the parent view:

fun <T: ViewBindingData> ViewGroup.inflateChildBinding(inflateBinding: (LayoutInflater, ViewGroup)->T): T =
    inflateBinding(LayoutInflater.from(context), this)

and use it like:

val binding = parent.inflateChildBinding(SomeBinding::inflate)
Tenfour04
  • 83,111
  • 11
  • 94
  • 154
0

Kotlin is no different from Java in case of abstractions, so I assume something like below will work

abstract class BindingElement<T: ViewDataBinding> {

    val binding: T

    abstract fun createBinding(LayoutInflater inflater, ViewGroup parent): T

    init {
        binding = createBinding(...)
    }
}

UPD: I noticed that your method requires field provided in constructor, so instead of init block you will use

constructor(parent: ViewGroup) {
    binding = createBinding(...)
}
Steyrix
  • 2,796
  • 1
  • 9
  • 23
0

It may look more like Kotlin code

abstract class BindingElement<T: ViewDataBinding>(
    val parent: ViewGroup
) {
    val binding = createBinding(..., parent)

    abstract fun createBinding(LayoutInflater inflater, ViewGroup parent): T

}

And this code is calling the non-final function in the constructor which is an unsafe operation.

WetABQ
  • 1