koin-annotations icon indicating copy to clipboard operation
koin-annotations copied to clipboard

KMP Expect classes that implement an interface throw "class is not abstract" error

Open AmkSk opened this issue 1 year ago • 3 comments

Describe the bug In our multi-module KMP project, we are using expect/actual classes. We added the new Koin annotations to the project and the kspCommonMainKotlinMetadata gradle task throws an error. The following class, which extends KoinModulesProvider interface (defines a single method provideModules()) shows an error:

expect class XyModuleProvider() : KoinModulesProvider

Error: Class 'XyModuleProvider' is not abstract and does not implement abstract member 'provideModules'.

Is this a bug or a behavior, that will not change?

Expected behavior No code change is required

Current Fix Override the interface method in the expect class and use actual override in the actual implementations of the expect class.

Koin project used and used version koin-core = "4.1.0-Beta1" koin-annotations = "2.0.0-Beta3" koin-compiler = "2.0.0-Beta3"

AmkSk avatar Jan 09 '25 12:01 AmkSk

what your KoinModulesProvider provides? is it working in non KMP project?

arnaudgiuliani avatar Feb 19 '25 18:02 arnaudgiuliani

It is used in a KMP project. KoinModulesProvider is an entry point for the client apps, that do not use Koin to set up the KMP library and provide data needed for Koin dependencies to work

For example this is how the iOS app sets up logging:

class IosNetworkLoggerModuleProvider(private val networkLogger: NetworkLogger) : KoinModulesProvider {

    override fun provideModules(): List<Module> = listOf(
        module {
            single<NetworkLogger> { networkLogger }
        },
    )
}

AmkSk avatar Feb 21 '25 08:02 AmkSk

coupling it to Module is not ideal, for now. Class module are intended to be agnostic for now. Let's see it as a feature proposal for 2.1

arnaudgiuliani avatar Feb 24 '25 11:02 arnaudgiuliani

@AmkSk isn't this a K2 issue linked to expect classes implementing interfaces?

https://youtrack.jetbrains.com/issue/KT-59739/K2-MPP-reports-ABSTRACTMEMBERNOTIMPLEMENTED-for-inheritor-in-common-code-when-the-implementation-is-located-in-the-actual

I guess you should explicitly indicate the KoinModulesProvider functions as override in your expect declaration and then mark actual the implementation of these functions.

interface Foo {
  fun bar()
}

expect class FooImpl : Foo {
  override fun bar()
}

// in platform source sets

actual class FooImpl : Foo {
  actual override fun bar() {}
}

I had the same on my side for another case unrelated to Koin and changing that way fixed the issue.

What I don't understand though, is that it worked like a charm, I just added iOS target, it was working, and only ./gradlew --info fails like that, IDE is fine, another gradle task seems fine too…

opatry avatar Jun 27 '25 21:06 opatry

anyone tried with last Koin updates?

arnaudgiuliani avatar Jul 11 '25 15:07 arnaudgiuliani

let's reopen if needed

arnaudgiuliani avatar Oct 20 '25 13:10 arnaudgiuliani