0

I use sealed classes to distinguish normal functions from suspend functions.

sealed class Function {
  class SuspendFunction(val execute: suspend () -> Boolean) : Function() {
    suspend operator fun invoke() {
      execute()
    }
  }

  class NormalFunction(val execute: () -> Boolean) : Function() {
    operator fun invoke() {
      execute()
    }
  }
}

Then I need some data to display in the display layer, I use enum.values().

enum class Work(val function: Function) {
  A(Function.SuspendFunction { true }),
  B(Function.NormalFunction { true })
}

Then I need to do various follow-up operations against Work.function.

fun run(work: Work) {
  when (work) {
    Work.A -> {
      work.function()
    }
    Work.B -> {
      
    }
  }
}

But this throws an error:

Expression 'function' of type 'Function' cannot be invoked as a function. The function 'invoke()' is not found

I think IDE no smart cast Function to NormalFunction.

This puts me in an embarrassing situation, I don't know how to choose to use enum or sealed class or hashmap.

  1. In the current situation, I may only use as to manually modify the type, which is not elegant.
  2. If I replace enum with hashmap, it should be able to solve the problem that the IDE cannot smart cast. But when using the use statement, it loses the characteristics of enum or sealed class.
  3. If I use sealed class instead of enum, the sealed class cannot be traversed, that is, you cannot use it like this enum.values().

What is the best solution in this case?

SageJustus
  • 631
  • 3
  • 9
  • 2
    Why make it complicated? You could just exclusively use `suspend` functions for your tasks since you're going to have to launch coroutines anyway to be able to run the ones that are suspending. – Tenfour04 Apr 17 '23 at 05:37
  • @Tenfour04 Since `Work.function` may also not be a `suspend` function, there is no need to start a coroutine. – SageJustus Apr 17 '23 at 06:44
  • What I mean is, you’re adding a lot of complexity to only *sometimes* avoid starting a coroutine. Can’t you just launch coroutines for all of them? – Tenfour04 Apr 17 '23 at 06:56
  • @Tenfour04 Yes, I can launch coroutines for all of them. But this brings up another question, will this have unexpected results? I don't know. – SageJustus Apr 17 '23 at 07:13
  • 3
    There can be unexpected results from coroutines if you aren't familiar with how they operate, but if that's the case, you'll have unexpected results for your suspend functions, too. – Tenfour04 Apr 17 '23 at 07:16
  • It won't make anything wrong if your code is already correct. – Louis Wasserman Apr 17 '23 at 09:30
  • @LouisWasserman Yes, but requires multiple use of `as`. or you mean use `suspend` function not make anything wrong? – SageJustus Apr 17 '23 at 10:03
  • I mean you should eliminate this whole thing and use suspend functions everywhere, as advised by @Tenfour04. – Louis Wasserman Apr 17 '23 at 16:25
  • For example, eliminate the sealed class and change your enum to directly use suspend functions: `enum class Work(val function: suspend () -> Boolean) { ...` No need to overcomplicate. – Tenfour04 Apr 17 '23 at 17:34

0 Answers0