Thread
#compose
    e

    eygraber

    1 year ago
    If I have an interfacez:
    interface Renderer {
      fun render()
    }
    
    interface ComposeRenderer : Renderer {
       @Composable override fun render()
     }
    will the compose mechanics work correctly if I call
    render
    polymorphically?
    class MyActivity : AppCompatActivity {
      private val renderer: Renderer = object : ComposableRenderer ...
      override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent { renderer.render() }
      }
    }
    Albert Chang

    Albert Chang

    1 year ago
    As long as you also specify
    @Composable
    in your interface because
    @Composable
    changes the signature of the function.
    e

    eygraber

    1 year ago
    In this case the value of rendereris inlined, so it's easy to see that it's an instance of
    ComposableRenderer
    . What about a case where the compiler can't deterministically see that it's a
    ComposableRenderer
    ?
    Albert Chang

    Albert Chang

    1 year ago
    Composable functions are just standard functions with some extra parameters. They don't break the rules of Java/Kotlin including polymorphism.
    e

    eygraber

    1 year ago
    Don't those extra parameters have to be added to the call site? How would the compiler know to add them?
    Albert Chang

    Albert Chang

    1 year ago
    The compiler plugin takes care of transforming the signatures of composable functions/lambdas and the invocation of them. I don't think there's much doc on these (as they are implementation details that may change from time to time) but if you are interested you can always read the source or check the byte code.
    e

    eygraber

    1 year ago
    I was mostly asking rhetorically, as it's really just a restating of my question. When the compiler runs, it sees this as a call to
    Renderer.render
    which is not marked as composable. It has no idea that the actual Renderer implementation is
    ComposableRenderer
    , so I'd imagine that it wouldn't transform the signature. My question is then essentially, is there any way the compiler can infer that this actually is a composable call, and if not, I just want to confirm that the composable function wouldn't work.
    Albert Chang

    Albert Chang

    1 year ago
    That is exactly why it works only if you also specify 
    @Composable
     in your interface.
    hfhbd

    hfhbd

    1 year ago
    interface ComposeRenderer : @Composable () -> Unit
    In theory, this should work too, but I never tried it out.
    e

    eygraber

    1 year ago
    The problem is I need
    Renderer
    and
    ComposeRenderer
    to stay as declared above.
    Zach Klippenstein (he/him) [MOD]

    Zach Klippenstein (he/him) [MOD]

    1 year ago
    Does that even compile? I’d be surprised if it does, because composable functions have an entirely different signature than non-composable ones, so as far as the compiler is concerned that override isn't even valid. It’s like suspend functions: you can’t override a non-suspend function with a suspend function, or call a non-suspend function and expect it to suspend.
    You can’t call a composable function from a non-composable function because the compiler needs to pass in some extra arguments and if the caller is not composable then it doesn’t know where to get those extra values.