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

ansman

09/16/2019, 2:39 AM
Is there any way to get the typealias target type when overriding a method on a specific platform:
Copy code
// Common
expect class Input

interface Foo {
  fun doStuff(input: Input)
}

// JVM
actual typealias Input = InputStream

// Use site
object : Foo {
  // I want this type to be `InputStream` when implementing this
  override fun doStuff(input: Input) {
    ...
  }
}
n

Nicholas Bilyk

09/16/2019, 2:15 PM
Common can't see platform-specific code, so if object : Foo is in Common, it can't see jvm's InputStream. If Foo is in JVM, then you can safely do this: `` override fun doStuff(input: Input) { input as InputStream } ``` The reason being that your JVM backend is what supplied actual Input, and you know it supplied InputStream as that type. (the typealias has nothing to do with it)
a

ansman

09/16/2019, 2:17 PM
I should have mentioned that “Use site” is not in the common codebase but rather in the consumer project which is likely platform specific. Also, you wouldn’t have to cast it since
input
is already a
InputStream
. You can actually just change the argument type to be
InputStream
. Most of my `expect`s are
internal
to not pollute the global namespace but then the default implementation is red since
Input
is not accessible
n

Nicholas Bilyk

09/16/2019, 2:19 PM
I assumed you couldn't change the argument type because possibly common code is what passes the argument.
a

ansman

09/16/2019, 2:19 PM
It’s more of an IDE question I suppose. Ideally I would never want to leak my
expect
types to the consumer if it’s a
typealias
n

Nicholas Bilyk

09/16/2019, 2:26 PM
I guess I don't really understand what you mean by "leak your expect types". The types for expect should be your common interface. For input streams, buffers, things like that where you have multiple platforms, the way I typically approach it is to define a common interface in common, then take the native backend implementations, such as InputStream, Buffer, etc and write a wrapper that uses the native implementation in the 'common' way. However, sometimes that's too much work and it's easier to do closer to what you're doing and just make up a type that always gets coerced at the platform's use site. Either way though the expect type should be however it's used in common code.
a

ansman

09/16/2019, 2:28 PM
So for example regarding
Input = InputStream.
I don’t want consumers of the library to have to feel like it’s a separate type when it’s actually just an
InputStream
. Ideally the fact that it’s called
Input
in the common code should be an implementation detail and should not concern the consumers
n

Nicholas Bilyk

09/16/2019, 2:31 PM
well, it has to be a separate type when it's common code or anything you're trying to expose to common
a

ansman

09/16/2019, 2:32 PM
Of course, but I just wish there was a way to keep that definition from being visible to the consumer which would only see the typealias target
n

Nicholas Bilyk

09/16/2019, 2:33 PM
oh I think I get what you're saying now
a

ansman

09/16/2019, 2:34 PM
When implementing the interface on the Jvm it would be great if
Input
didn’t exist for them. I hoped making it
internal
would do just that and I suppose it did to some extent. But instead you get compile errors unless you manually change
Input
to
InputStream
n

Nicholas Bilyk

09/16/2019, 2:35 PM
yeah, I could imagine a way if common code never got compiled as its own thing, but common does get created as its own library
I hit kind of the same thing, for almost the same place - I have a common interface for buffers, but some platform code needs the actual buffer object, so I have to cast
I do this which has the same problem you have:
Copy code
interface NativeReadBuffer<T> : ReadBuffer<T> {

	/**
	 * Returns the underlying native implementation of this Buffer. For JVM it will be an nio.Buffer object, for
	 * js it will be an ArrayBuffer
	 */
	val native: Any
}
It would be nice if I could do soooomething like: @JsType("ArrayBuffer") @JvmType("nio.Buffer") val native: Any
make sure you have a look at kotlin's multiplatform IO library, it might have a multiplatform way of doing input streams: https://github.com/Kotlin/kotlinx-io
a

ansman

09/16/2019, 2:45 PM
I’d be find with a
@JvmName
or something like that. I don’t need to specify the full path name but rather just a typealias