Hello, I have a Java base library and a same objec...
# multiplatform
x
Hello, I have a Java base library and a same objective-C base library. And there is a
Copy code
abstract class JavaAbsClass
in java library, and a
Copy code
class ObjcAbsClass
in objc library. So
Copy code
except abstract class CommonAbsClass
is defined in kmm commonMain module, and
Copy code
actual typealias CommonAbsClass = JavaAbsClass
that's not a problem in kmm jvmMain module. But in kmm iosMain module, not only
Copy code
actual typealias CommonAbsClass = ObjcAbsClass`
is unsupported, but also
Copy code
actual typealias CommonAbsClass = ObjcAbsClassWrapper
abstract class ObjcAbsClassWrapper:ObjcAbsClass()
will get a compiler error with
Non-final Kotlin subclasses of Objective-C classes are not yet supported
. So how should I do to interop abstract class with both jvm and objc library? Thanks very much!
b
Does your CommonClass has any properties, constructors or methods declared?
Easiest workaround would be this actual abstract class CommonAbsClass: ObjCAbsClass()
x
Yes, there are some extension properties and extension function to interop jvm and objc
b
When you use actual typealias, target signature must match EXACTLY to the expect declaration
So common pattern is to moddel your
expect
after one of the platform declarations and typealias to it on that platform while using actual wrapper on other platforms. e.g.:
Copy code
// commonMain
expect class File {
  fun getPath(): String
}

// jvmMain
actual typealias File = java.io.File

// iosMain
actual class File {
  actual fun getPath(): String {
    TODO("Delegate to some IOS or posix APIs for this")
  }
}
x
I have try it. But another problem is that if other class refer this interop subclass, the original class type is missed
b
Also note that extension functions are not part of class signature so to expand on the above example you could just as well do this without breaking typealias on jvm
Copy code
// commonMain
...
expect fun File.veryCustomMethod()

// jvmMain
...
actual fun File.veryCustomMethod() = println("works")

// iosMain
...
actual fun File.veryCustomMethod() = println("works")
You can extend native classes and interfaces on actual declaration if they're not final.
Copy code
...
// iosMain
actual class File: SomeObjCFileClass() {
  actual fun getPath(): String {
    TODO("Delegate to some IOS or posix APIs for this")
  }
}
x
extend classes got another problem.
Copy code
//commonMain
except class CommonAnotherClass
except var CommonAnotherClass.file : File

//iosMain
actual typealias CommonAnotherClass = ObjCAnotherClass
actual var CommonAnotherClass.file : File
    get() = this.getFile() //type mismatch. Return SomeObjCFileClass type defined in objc library
    set(value){
        this.setFile(value)
    }
b
What exactly this.getFile() return? It must return your File from commonMain, not native alternative
x
this
is a ObjCAnotherClass object.
b
No,
this
is
CommonAnotherClass
You need to understand that with this approach, on jvm
java.io.File == File
(since it's typealias), but on ios `ObjCAnotherClass != File`(since File just extends CommonAnotherClass)
Can you drop relevant code you have for all three - common, jvm and ios? Might be easier to explain what's wrong using specific examples
x
Sorry. Yes,
this
is NOT ObjCAnotherClass. But
this.getFile()
returned SomeObjCFileClass defined in objc library
b
Right, so THAT is what's wrong, since expected return type is File. Remember, if you have
class A: B()
, then
B() is A()
but
A() !is B()
x
How to solve that?
b
You need to wrap your ObjCAnotherClass in File. If it's an interface this can work
Copy code
actual class CommonAnotherClass(delegate: ObjCAnotherClass): ObjCAnotherClass by delegate

actual var CommonAnotherClass.file : File
    get() = CommonAnotherClass(this.getFile()) 
    set(value){
        this.setFile(value)
    }
❤️ 1
x
actual var CommonAnotherClass.file : File
How to interop with objc
SomeObjCFileClass.getFile()
b
Again, I need to see the actual code on all three sourceSets to assist you properly
x
Okay, I'll show my code at tomorrow. I am in China and on the subway after get off work at this time 🤣
👍 1
Now using android slack app to ask for advice.👀
actual class CommonAnotherClass(delegate: ObjCAnotherClass): ObjCAnotherClass by delegate
It seems a workaround for me. I'll try tomorrow. Thanks!
@Big Chungus Here is a demo repo: https://github.com/xiaobailong24/KMMAbsClazzDemo
@Big Chungus Any idea with this demo?
Find an imperfect solution: