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

Orhan Tozan

05/19/2020, 11:39 PM
What are pros/cons of using actual/expect instead of interfaces and implementations? I think that interfaces/impls have the following advantages over actual/expect 1. It is more flexible. You can have multiple impls for the same interface, they are easily interchangeable, as opposed to actual expect 2. Interfaces and impls is a concept everyone already understands. Expect and actual provide a different syntax without much added value IMO I'm curious what people's thought about the two are. Let's discuss.
a

araqnid

05/20/2020, 1:01 AM
It’s likely you’d use both at once: for example, having an interface and an
expect
factory function defined in common, and then an implementation of the interface and an
actual
for the factory function defined in each platform.
e

Erik Christensen

05/20/2020, 1:41 AM
`expect`/`actual` is more like a platform
#ifdef
in C or C++ (or compiling different source files for each platform that implement functions defined in a common header file). You could
expect
an interface in common code, but then have the
actual
interface be a Java Standard Library interface on JVM and something else on a native platform where that interface doesn't exist. You can't accomplish that with traditional interfaces and implementations. There are situations where you could use the two approaches interchangeably, but that's not always the case.
o

Orhan Tozan

05/20/2020, 2:27 AM
@araqnid why would you need an expect factory function? Cant the impl of the interface just construct it itself?
g

gildor

05/20/2020, 4:11 AM
actual/expect works not only for classes, but also for top level functions and companion objects, which you cannot achieve with interfaces
also it just a bit easier in some cases, you not always use interfaces in your single platform code, right? You sometimes don’t need interface as abstraction. So it’s the same here, if class works for you and doesn’t require interfaces, it also true for multiplatform, actual/expect doesn’t force you to introduce abstraction (and as result make it more complex to use), instead you keep using you platform class and provide other platfrom implementations
also good thing about actual/expect is that navigation between platform code is easier a bit, you always jump between implementation methods and IDE warns you when some new expect method is not implemented for one of platforms
a

araqnid

05/20/2020, 4:15 AM
@Orhan Tozan but you wouldn’t be able to do that from common code, like you can call Dispatchers.Default, for example.
r

russhwolf

05/20/2020, 12:37 PM
Expet/actual is nice for the use-cases that interfaces can't handle, but I tend to avoid using it when I can use an interface. For example I don't like expect classes with expect properties/functions inside of them, because there's no way to swap out an alternate implementation. In that case I'd rather do an interface and, if needed, an expect/actual factory function to construct it in common.
👍 2
k

kpgalligan

05/20/2020, 1:47 PM
I’m sure this is covered by the responses, but here’s my basic thought process. First, interfaces and lambda definitions are kind of in the same bucket, and I use them to define functionality that can be provided by the host platform. For purposes of discussion, assume
()->Whatever
is just shorthand for an interface with one function.
Interfaces have a lot more flexibility, as you can just pass in the implementation from the host, and you can more easily support fakes in testing. Passing in a lambda from swift can be much easier than trying to write cinterop code, then wiring that with expect/actual. For example, if you want to use Firebase analytics, you can just pass in a Swift callback. The alternative is using cinterop to import all of Firebase core and analytics, which is a lot of config for very simple functionality.
I do a lot more exepct/actual with functions than classes, etc, and “a lot” is not much.
o

Orhan Tozan

05/20/2020, 1:51 PM
I see a point there, expect/actual is unmissable for KMP functional programming
k

kpgalligan

05/20/2020, 1:51 PM
However, bridging native API’s is a whole different use case. I talk about that here. https://vimeo.com/371460823. Doing that with interfaces would be pretty messy.
Well, on functional programming, I mean you can pass in lambda definitions. I sometimes use expect actual for functions more out of convenience.
If the function you want to call is available in the platform without additional cinterop, and easy to call, expect/actual is simpler.
printStackTrace
as an example (yes, I know that’ll be standard in 1.4)
To put this another way, as libraries mature, I think it’s reasonable for somebody to write a whole app’s worth of shared code and have zero expect/actuals