77 lines
2.2 KiB
Plaintext
77 lines
2.2 KiB
Plaintext
![]() |
== Why is this an issue?
|
||
|
|
||
|
An interface that declares only a single function should be marked as function interface.
|
||
|
Function interfaces can be instantiated from lambda expressions directly and are, therefore, more comfortable to use.
|
||
|
|
||
|
|
||
|
Also, consider using a function type instead of a function interface.
|
||
|
In many situations, a function type is sufficient.
|
||
|
A function interface is only required when the function must not be anonymous
|
||
|
or when an object should implement multiple function interfaces at once.
|
||
|
|
||
|
=== What is the potential impact?
|
||
|
|
||
|
==== Complexity
|
||
|
|
||
|
When an interface is declared _functional_, SAM conversion is enabled.
|
||
|
This means that any lambda expression that matches the interface's single function's signature
|
||
|
can be converted into an instance of the interface,
|
||
|
without the need for an
|
||
|
explicit class or singleton object to implement the interface.
|
||
|
|
||
|
==== Wrong logic
|
||
|
|
||
|
An interface can still be marked `@FunctionalInterface` in Kotlin,
|
||
|
but this has no effect, and SAM conversion will not work.
|
||
|
The annotation `java.lang.FunctionalInterface` is only a Java platform type with no special meaning in Kotlin.
|
||
|
|
||
|
== How to fix it
|
||
|
|
||
|
Replace `interface` with `fun interface`.
|
||
|
If the interface is annotated with `@FunctionalInterface`, remove the annotation.
|
||
|
|
||
|
=== Code examples
|
||
|
|
||
|
==== Noncompliant code example
|
||
|
|
||
|
[source,kotlin,diff-id=1,diff-type=noncompliant]
|
||
|
----
|
||
|
interface IntMapper<T> { // Noncompliant
|
||
|
fun map(value: Int): T
|
||
|
}
|
||
|
|
||
|
interface StringMapper<T> { // Noncompliant
|
||
|
fun map(value: String): T
|
||
|
}
|
||
|
|
||
|
@FunctionalInterface // Noncompliant
|
||
|
interface ProgressCallback {
|
||
|
fun progressChanged(percent: Double)
|
||
|
}
|
||
|
----
|
||
|
|
||
|
==== Compliant solution
|
||
|
|
||
|
[source,kotlin,diff-id=1,diff-type=compliant]
|
||
|
----
|
||
|
fun interface IntMapper<T> { // Compliant, function interface used
|
||
|
fun map(value: Int): T
|
||
|
}
|
||
|
|
||
|
typealias StringMapper<T> = (value: String) -> T // Compliant, functional type used
|
||
|
|
||
|
fun interface ProgressCallback { // Compliant, function interface used
|
||
|
fun progressChanged(percent: Double)
|
||
|
}
|
||
|
----
|
||
|
|
||
|
== Resources
|
||
|
|
||
|
=== Documentation
|
||
|
|
||
|
* https://kotlinlang.org/docs/fun-interfaces.html[Kotlin Docs, Functional (SAM) interfaces]
|
||
|
|
||
|
=== Articles & blog posts
|
||
|
|
||
|
* https://www.baeldung.com/kotlin/sam-conversions[Baeldung, SAM Conversions in Kotlin]
|