yigit
11/26/2024, 11:41 PMyigit
11/26/2024, 11:41 PMexpect class Foo {
fun commonMethod()
}
impleemnted in jvm, android and ios.
Android & JVM implementations cannot be implemented on the same sourceSet but I want them to have more common functions so that any downstream sourceSet that is shared in between use those APIs.
e.g.
jvm:
actual class Foo {
fun commonMethod() {}
fun commonJvmArt() {}
}
android:
actual class Foo {
fun commonMethod() {}
fun commonJvmArt() {}
fun androidSpecific(context: Context) {}
}
Is there any way I can expand the scope of Foo
in a common source set between jvm & android. (lets call it jvmAndroidMain)
For instance, my tests are mostly in jvmAndroidTest sourceSet, and there I can write a test like:
@Test fun testFoo() {
val subject = Foo()
subject.commonJvmArt()
}
And this compiles just fine but IDE really doesn’t like it :( Which breaks the user experience.yigit
11/26/2024, 11:42 PMjvmAndroid
and make my actuals on jvm and androidx extend it, but then the intermediate super class leaks in the API surfaceyigit
11/26/2024, 11:58 PMjvmAndroid
but i’m not super confident that this is WAI or a bug where it doesn’t check.yigit
11/26/2024, 11:59 PMexpect class Foo {
fun commonMethod()
}
jvmAndroidCommon:
expect class Foo {
fun commonMethod()
fun androidJvmMethod()
}
yigit
11/27/2024, 12:50 AMFileSystem.SYSTEM
but they basically redeclared a shadowed properly which I cannot here (these classes are designed to be overridden)Ahmed na
11/27/2024, 1:02 AMjvmAndroidMain
target with a extension function help ?
// in jvmAndroidMain
fun Foo.commonJvmArt()
androidMain {
dependsOn(jvmAndroidMain.get())
}
you should be able to use in android
target tooyoussef hachicha
11/27/2024, 4:51 AMyigit
11/27/2024, 5:02 AMyigit
11/27/2024, 5:05 AM// common
expect abstract class Foo
// nonWeb
expect abstract class Foo {
abstract fun doSomething()
}
// web
expect abstract class Foo {
abstract *suspend* fun doSomething()
}
// android
expect abstract class Foo {
fun doSomething() {} // due to backwards compat
abstract fun doSomethingElse()// backwards compat
}
For anyone wanting to use with web from common, we’ll provide a suspending doSomething but everyone else, we prefer the non-suspending…Ahmed na
11/27/2024, 6:48 AMsuspend
and runBlocking
not available for js
I wish there was a easier way to solve it too ! ,
but i ended up shadowing it
I used 2 classes (one internal and one public) ,
but you can try internal
directly too
And only expose the fun
to the needed platform with extension function
// common
expect abstract class Foo {
internal abstract suspend fun _doSomething()
internal abstract fun _doSomethingElse()
}
-------------------------
// nonWeb
actual abstract class Foo {
internal abstract suspend fun _doSomething() {// real logic}
internal abstract fun _doSomethingElse() {// empty logic}
}
fun Foo.doSomething(){ runBlocking {_doSomething()} }
----------------------
// web
actual abstract class Foo {
internal abstract suspend fun _doSomething() {// real logic}
internal abstract fun _doSomethingElse() {// real logic}
}
fun Foo.doSomething(){ runBlocking {_doSomething()} }
fun Foo.doSomethingElse(){ doSomethingElse() } // expose doSomethingElse only for web
yigit
11/27/2024, 4:25 PMrusshwolf
11/27/2024, 6:10 PMyigit
11/30/2024, 10:45 PMeygraber
12/01/2024, 1:31 AM// Utility.common.kt
expect class Utility {
fun commonAction()
}
// Utility.jvmAndroid.kt (alternatively provide different implementations for jvm and Android)
class JvmAndroidUtility {
fun commonAction() {}
fun openFile(file: File) {}
}
expect typealias Utility = JvmAndroidUtility
I'm not sure if the typealias trick is sticking around long term though.
Another way to do this would be with an interface and an expect/actual factory function (which I think is the currently preferred way while expect/actual classes aren't fully API stable).yigit
12/01/2024, 4:01 AMactual
?
It is probably worth adding to the ticket but that still has the same problem as the one I mentioned in the ticket (getting a new public unwanted JvmAndroidUtilty
public API).
Interface with factory functions are also a nice solution but because these apis already existed on Android, we cannot remove them or change them into interface without breaking API,😫.
Thanks for the suggestions though.eygraber
12/01/2024, 6:19 AMactual
.
If the API already exists on Android then wouldn't that serve as the target of the typealias, and there would be no additional public API? Although I guess the expect class would have to have a different name, and then that becomes an additional public API?
Another option (which I thought wouldn't work, but it seems like it does work in 2.1.0) is:
actual class Utility {
actual fun commonAction() {}
fun open(file: File) {}
}
I like your request too (although I'd prefer override expect class
over an annotation).yigit
12/02/2024, 12:16 AM