Overloading using extension method


#1

Hi,

I’m new to Kotlin and I am trying to implement Kotlin DSL for http://spreadsheet.dsl.builders/

I hope it would be as easy as writing extension methods to current interfaces, e.g.

public interface SpreadsheetBuilder {
    void build(Configurer<WorkbookDefinition> workbookDefinition);
}

will be extended with the proper receiver

fun SpreadsheetBuilder.build(workbookDefinition: WorkbookDefinition.(WorkbookDefinition) -> WorkbookDefinition) {
    return this.build {
        workbookDefinition(it, it)
    }
}

but I found that still the first method is resolved when I try to write

        PoiSpreadsheetBuilder.create(excel).build {
            sheet("test") {
                row {
                    cell { value("Hello World") }
                }
            }
        }

the original Java build method is resolved. Is this an intention? I would expect that method accepting function would have the preference to the method accepting SAM type. Any ideas how to fix this other than creating some stupid names such as _build or so?

I think more frameworks might take advantage of such a feature that SAM types will be replaced with functions with receivers


#2

As explained here: https://kotlinlang.org/docs/reference/extensions.html (section ‘Extensions are resolved statically’) , if a class has a member function, and an extension function is defined which has the same receiver type, the same name and is applicable to given arguments, the member always wins.

In other words when method build (Configurer<WorkbookDefinition> workbookDefinition) is called on a class implementing interface SpreadsheetBuilder (assuming it was earlier cast to type SpreadsheetBuilder - see the same page and section as before) Kotlin uses whatever implementation of member function that class has, rather than calling the extension function.

You should simply create your own implementation of the interface and make sure it’s returned by create method of PoiSpreadsheetBuilder class.


#3

thanks, @forinil2. I’ve seen that documentation before but the method is not exactly the same. in my point of view, method accepting function with the receiver is more special than the one accepting Configurer<WorkbookDefinition>.

There is no point to create shadow interface structure just for single language for the framework. Developers still can use the framework the Java way but they won’t gain any bonus in less repetition.


#4

I’ve resolved issue in the tracker but I have no clue what is the outcome:

https://youtrack.jetbrains.com/issue/KT-12848

I would be able to add annotation to that Java interface Configurer.