s

    Sylvain Patenaude

    2 years ago
    Dumb quick question: can we implement an extension method with the
    expect
    /
    actual
    pattern? EDIT: Looks like it's doable, but the method I want to split is not an extension method after all. So my question is rather: Can we have only some methods of a class that are prefixed with
    expect
    or does it have to be the full class at that point? For instance, I would have a class where pretty much all methods would be 'common' except for a few that would need to be implemented natively.
    russhwolf

    russhwolf

    2 years ago
    An expect class needs to have only expect declarations. Follow/star https://youtrack.jetbrains.com/issue/KT-20427 to change that. There’s a couple strategies you can use as workarounds such as having your expect class extend another class/interface that includes your default/shared implementations, or putting your common implementations in extension functions.
    d

    Dmitri Sh

    2 years ago
    exactly my question from last night. came across the same problem: ith an expected class in shared, not possible to have any method implementation? All methods must be actualized in platform specific actuals? I have a class (decorator) that can have some of its methods actually implemented in shared - but am forced to duplicate the code in actuals. Is this (no pun intended) "expected"? Seems like a waste.
    ankushg

    ankushg

    2 years ago
    @Dmitri Sh Would declaring extension functions on your expected class in your common code help reduce duplication? Edit: looks like Russell beat me to it 😊
    russhwolf

    russhwolf

    2 years ago
    It’s the current state of things but it won’t be that way forever. This sort of rough edge is what comes with being an early adopter to a new technology like this.
    s

    Sylvain Patenaude

    2 years ago
    Good point @russhwolf. I will use extension functions as needed. I can't extend another class since I'm using objects. My methods are kind of static, more like helper functions.
    russhwolf

    russhwolf

    2 years ago
    Objects can extend interfaces if that helps, but extension functions work just as well if you don’t need to be able to override.
    s

    Sylvain Patenaude

    2 years ago
    I know that objects can extend interfaces, but that would mean that my interface would have some default implementation in this case? While feasible, I think the code will be clearer with extension functions. Interfaces with only default code (without real abstract methods) would look weird to me.
    Can we have static methods (or
    companion
    methods in Kotlin terms) in an
    interface
    ? Basically my pattern would look like this:
    expect object Helper : HelperCommon { // HelperCommon would either be a class or interface with static methods only
        expect fun function1() // specialized natively
        expect fun function2() // specialized natively
        ...
    }
    Now from another class, I would like to be able to call the functions in
    HelperCommon
    through
    Helper
    like this:
    val someValue = Helper.functionCommon1(...) // functionCommon1 would be static/companion in HelperCommon
    At first I wanted to use extension functions, but they behave like member functions while my functions are meant to be static.
    russhwolf

    russhwolf

    2 years ago
    You can’t have an
    expect companion object
    in a non-expect class/interface. But you could have a non-expect
    object Helper
    and have its methods delegate to
    internal expect
    functions which then have separate implementations per-platform.
    s

    Sylvain Patenaude

    2 years ago
    But the internal expect functions would be at module level instead of object level, right? So I wouldn't be able to call Helper.functionThatIsNativelySpecialized().
    russhwolf

    russhwolf

    2 years ago
    Well, doesn’t have to be internal, I just figured you might want to limit scope
    internal would mean consumers can only interact with it through
    Helper
    s

    Sylvain Patenaude

    2 years ago
    I may be stubborn, but I'm looking for a workaround for the current Kotlin limitation that we mention above and offer a unified interface to calling clients like this: val someVal1 = Helper.commonFunction() val someVal2 = Helper.specializedFunction() //expect/actual
    russhwolf

    russhwolf

    2 years ago
    Right I might be losing track of your actual use-case
    s

    Sylvain Patenaude

    2 years ago
    So you're saying
    internal
    would do this? I thought it was just a visibility modifier for the callers in same module.
    russhwolf

    russhwolf

    2 years ago
    No not quite saying that
    s

    Sylvain Patenaude

    2 years ago
    My other option is to have 2 separate objects, like
    HelperNative
    and
    HelperCommon
    for instance, but if I can avoid it that would be better.
    russhwolf

    russhwolf

    2 years ago
    object Helper {
        fun commonFunction() {
            // .. common impl
        }
        fun specializedFunction() = specializedFunctionInternal()
    }
    
    expect fun specializedFunctionInternal() // Will have separate impl
    you can do something like that where you delegate so the caller only needs to talk to one object
    You might make
    specializedFunctionInternal
    have
    internal
    visibility so people don’t call it directly, but you don’t have to
    and you could wrap
    specializedFunctionInternal()
    in a
    HelperNative
    object if you want but it’s not necessary
    s

    Sylvain Patenaude

    2 years ago
    That would work. The only minor caveat is that clients from the same module/package could still call it directly if they wanted, but it's no big deal.
    russhwolf

    russhwolf

    2 years ago
    Yeah that’s where you could make it
    internal
    and have
    Helper
    live in its own module
    s

    Sylvain Patenaude

    2 years ago
    Unless I put the
    specializedFunctionInternal()
    function
    private
    ? Can you have a
    private expect fun function()
    ?
    russhwolf

    russhwolf

    2 years ago
    No I think it needs to be
    public
    or
    internal
    s

    Sylvain Patenaude

    2 years ago
    Ah ok, I tried. 😉 I miss the good old days when I was using
    private virtual
    functions in C++. Thank you very much for your help @russhwolf.
    d

    Dmitri Sh

    2 years ago
    @ankushg not sure how extensions would help me avoid code duplications here, can you clarify? Btw -I was searching the other day for a way to add Parcelable support to a common data class, and came (I think, based on the name) your article on that - and was able to do exactly that, so thanks for that!
    @russhwolf sure, I understand I am an early adopter and this sort of thing comes with the price - I was not so much complaining as asking if I misunderstood something
    ankushg

    ankushg

    2 years ago
    @Dmitri Sh In some simple cases, you can take an
    expect class SpecialClass
    and define an extension
    fun SpecialClass.doSomething()
    in common code. This way, if your implementation of
    doSomething
    is identical across platforms, you can still define it once in Common code, even though you aren't technically allowed to have it inside your
    expect class
    declaration. Any yup that was me 😊 Glad it was helpful!
    d

    Dmitri Sh

    2 years ago
    interesting, I didn't realize I could do that in common code - previously I defined extensions for working with dates in android and iOS code, maybe I can move that to common. And yes, that article was very helpful!