```fun interface Foo : () -> Unit fun interfac...
# compiler
s
Copy code
fun interface Foo : () -> Unit

fun interface Foo1 : Foo
fun interface Foo2 : Foo

fun test(foo: Foo2) {
    println(foo)
}

fun main() {
    val instance = object : Foo1 {
        override fun invoke() {
        }
    }
    test(instance) // is this allowed by design?
}
Maybe I'm not smart enough to understand why this is allowed, it makes me feel confused, is there any particular reason to support this behavior?
r
Hi @scaventz, take this with a grain of salt but I believe it’s by design because
fun interface
values are coerced into any argument that can be desugared into the abstract method of the fun interface based on its shape. I think this kind of structural matching is their primary feature beyond the Function syntax for constructors in which you can avoid declaring an
object
. This should also work:
Copy code
test(Foo1 {})
or
Copy code
fun test(f: () -> Unit)
Foo1, Foo2 and Foo as well as anonymous lambdas that return Unit and have no arguments are valid structurally because all of them can dispatch to the abstract method you are not implementing when extending
() -> Unit
. fun Interfaces can’t hold state on their own, can’t have more than one abstract method and can’t include variance or additional type arguments in their members beyond those declared in the interface. I believe these requirements are there so structural matching against target arguments always desugar correctly in all cases by dispatching to the abstract method of a known shape. I’m curious if there is a case or you think accepting a subtype like in this case
Foo2
is dangerous or should be restricted. I can see how it can be puzzling though unless you know some of these rules
e
Yes, that’s by design.
instance
is a subtype of
() -> Unit
which is a function type. Function types in Kotlin are structural (they are determined by their structure, while is their parameter types and return type), just like a lambda
{…}
in Kotlin (which is also structural). Such structural types in Kotlin are automatically converted to the named types (like
Foo2
in this example), which have a matching shape (for functional types a matching shape means
fun interface
with a method that has the corresponding signature).
👍 1
s
@raulraja Thank you for your reply, it is very helpful to me. I don't think it is dangerous or should be restricted, I just want to be sure because it is a case related to KT-46908
👍 1
@elizarov Thank you! It looks natural to me now