https://kotlinlang.org logo
#multiplatform
Title
# multiplatform
a

Anton Afanasev

06/04/2021, 7:16 PM
Hi here! How do you usually handle code that is sharable between platforms, but have unique or platform specific dependencies? For instance my expected constructor has 1 mandatory argument that I would like to share between platforms.
Copy code
expect class MailBox(firstName: String) {}
Now, I want that my Android actual implementation will have some Android specific object passed as well. Lets say Context I can not do
Copy code
actual class MailBox actual constructor(firstName: String, context: Context) // not allowed as actual constructor does not match the expected.
If I use a secondary constructor, I cannot be sure that it will be called and therefore Context is going to be of
Nullable
type and smell.
Copy code
actual class MailBox actual constructor(firstName: String) {
    private var context: Context? = null // Context is of Nullable - not nice
    
    constructor(context: Context, firstName: String = "Bobby", ) : this(firstName) {
        this.context = context
    }
Obviously, I can declare my expected without primary constructor - but then I have no control over each platform passing a mandatory argument.
Copy code
expect class MailBox {} //commonMain

actual class MailBox(context: Context, firstName: String) {} //androidMain

actual class MailBox(firstName: String) {} //iOSMain

//No ability to force passing `firstName` argument. Any platform can decide to modify/remove `firstName` on their will.
QUESTION: Are there any other, cleaner approaches that allows me to force some expected constructor values mandatory, while others can be platform specific?
d

Dominaezzz

06/04/2021, 7:59 PM
Hmm, maybe use poly-morphism instead of
expect
/
actual
.
k

kevindmoore

06/04/2021, 8:20 PM
Or just inject the context into that class
r

russhwolf

06/04/2021, 9:42 PM
If
firstName
is mandatory then maybe you want
Copy code
expect class Mailbox {
  val firstName
}
Then the `actual`s are forced to define it somehow, and the most natural path will be a constructor argument
Copy code
actual class MailBox(firstName: String) {
  actual val firstName = firstName
}
But I agree that using an interface or abstract class might be nicer for this.
a

Anton Afanasev

06/04/2021, 10:49 PM
Thanks for your input. @russhwolf, I was not clear enough when defined
firstName
as "mandatory". By "mandatory" I meant that I would like to keep this value injected in the constructor no matter what platform it is. Like with expect/actual I force all the platforms to respect this protocol. Thank you for your input