Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 346 Vote(s) - 3.52 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Interface as functions in Kotlin

#1
I am working on an android library that contains some views. Naturally these views can emit events.

I have an interface called (just for the purpose of this question) `Listener`. If I wrote the library in Java things would look like this:
```java
public interface Listener {
void onEvent();
}
```
```java
public class SomeView extends FrameLayout {
// Some more functions and implementation details

public void setListener(Listener l) { ... }
}
```

When using this view in a Kotlin activity I can use the `setListener` like this:
```Kotlin
someViewInstance.setListener {
// implementation
}
```

I want to write my library in Kotlin, but it might be used in Java code as well, so I want to provide and interface for the listener just like a regular view (like above) but have the option for Kotlin code to use the function implementation:
```Kotlin
interface Listener {
fun onEvent()
}
```
when I try to use `setListener` like above in my Kotlin test activity I get a compilation error saying that the function expects type `Listener` but got `() -> Unit`.

Is there a way to enable this kind of implementation in Kotlin without having to create a new function for this?

I thought about having just one function that receives `() -> Unit` but then it look weird in the Java code (`Function1` etc.).

Thanks!
Reply

#2
You can define your interface as suggested and also add an extension that allows the usage of a lambda which is more idimatic for Kotlin code.


class SomeView {
fun setListener(l: Listener) {}
}

fun SomeView.setListener(l: () -> Unit) = setListener(object : Listener {
override fun onEvent() = l()
})

In Java, you would still be able to pass the `Listener` implementation.
Reply

#3
This is called [SAM-conversions](

[To see links please register here]

),
> Just like Java 8, Kotlin supports SAM conversions. This means that Kotlin function literals can be automatically converted into implementations of Java interfaces with a single non-default method, as long as the parameter types of the interface method match the parameter types of the Kotlin function.

But
> Note that SAM conversions only work for interfaces, not for abstract classes, even if those also have just a single abstract method.
> Also note that this feature **works only for Java interop**; since Kotlin has proper function types, automatic conversion of functions into implementations of Kotlin interfaces is unnecessary and therefore unsupported.

So, you can't write a simple Kotlin code to simulate this call.

---
In **Java**, if you write a

public interface Listener {
void onEvent(); // SAM: Single Abstract Method. Only 1 is allowed
}

And you have a

public class SomeView extends FrameLayout {
// skip the constructors

public void setListener(Listener listener) {
// do something
}
}

Then you can do such a fancy call in Kotlin, thanks to SAM-conversion:

SomeView(this).setListener {} // asking a parameter with type () -> Unit for setListener
// Then parenthesis of function call can be omitted
// setListener function can also accept a parameter with type Listener
// by object : Listener {}

But if you convert that Java file into Kotlin, the code will report an error, due to the reason mentioned above. You have to implement a `SomeView.setListener(() -> Unit)` function by yourself, for example

fun SomeView.setListener(l: () -> Unit) {
listener = object : Listener{
override fun onEvent() {
l()
}
}
}
Reply

#4
for Kotlin 1.4+. It can use SAM-conversion for Kotlin functions if you mark an interface as a "functional" interface:

fun interface Listener {
fun onEvent()
}

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through