Should the following be possible: ```public seale...
# multiplatform
e
Should the following be possible:
Copy code
public sealed class Foo

public expect class Bar : Foo
When I define the actual class in the same package and module in a platform source set (e.g.
jvmMain
):
Copy code
public actual class Bar : Foo()
I get an error that says:
Copy code
Inheritance of sealed classes or interfaces from different module is prohibited
t
Sort of feels like it beats the purpose of sealed interfaces no? What is it that you're trying to do?
The rest of the compilation error also explains it more:
Copy code
Inheritor of sealed class or interface declared in package bar
but it must be in package foo where base class is declared
l
I find that mixing expects and no-expects in the same file gets confusing at times. I personally would write a separate expect PlatformBar and make bar wrap that.
e
Sort of feels like it beats the purpose of sealed interfaces no?
I'm not sure how that would beat the purpose of a sealed interface?
What is it that you're trying to do?
Essentially, I need platform specific behavior in one of the subclasses of a sealed class.
The rest of the compilation error
What I posted is the entirety of the error that I can see
I personally would write a separate expect PlatformBar and make bar wrap that.
I specifically need to not wrap it for this use case
t
Ah cool, then IntelliJ adds some extra text when I hover over the error.
l
What stops it from wrapping? If the public API for Bar is the same, it should still look the same externally. I don’t know what your use case is.
e
```Inheritor of sealed class or interface declared in package bar
but it must be in package foo where base class is declared```
In any case, it is declared in the same package and module, just a different source set
t
Maybe I don't understand sealed interfaces well enough, but the fact that it is sealed means that there should only be one definition, local to the module, of what this sealed class/interface actually contains. So declaring it outside of a module would beat the purpose.
e
It isn't declared outside of the module? Unless source sets are considered separate modules, but I didn't think that they are
t
I thought sourceSets are "seen" as modules on their own. Damn I'm learning a lot here! Sorry for not being able to contribute more! 😅
l
I know that publishing treats them as separate modules, but I don’t think the compiler does. I think the compiler just essentially inlines the actual for the corresponding source set.
e
That was my assumption as well
t
❤️
Soooo, then we wrap it instead?
l
Wrapping is what I generally go to when possible with expect/actual. It’s a little extra work, but worth it when there’s less to figure out when you run into a compiler error.
e
My use case doesn't allow it to be wrapped. For now, I'm just defining the parent sealed class as an expect and copying the implementation to each platform
l
Copy code
expect class PlatformBar(param: Type) {
    fun foo()
    val x: Int
}

class Bar(param: Type): Foo() {
    private val platform = PlatformBar(param)
    fun foo() = platform.foo()
    val x get() = platform.x
}
Should be indistinguishable from an external perspective. The only issue would be in the case of performance, no?
If you need anything from Foo, you can pass
this
into the PlatformBar constructor
e
That doesn't work for me because
Bar
is being used a sealed class itself that just has objects that extend it, and those objects are what differ based on platform
t
I feel like this discussion/question could really benefit from your actual code 😅 Can you share it somehow? Maybe obfuscate it beforehand.
l
I don’t know that it’s possible to do that. How would exhaustive when work in common code?
e
I specifically left that out because it doesn't affect the error that I'm seeing, but here it is:
Copy code
sealed class Typography {
  class Deferred(val lookup: Map<String, Typography>) : Typography()
}

expect sealed class PlatformTypography : Typography {
  object Title1 : PlatformTypography
  object Title2 : PlatformTypography
  object Title3 : PlatformTypography
}
l
What does your actual look like? Do you have
Copy code
actual sealed class PlatformTypography: Typography {
    actual object Title1: PlatformTypography() {...}
    actual object Title2: PlatformTypography() {...}
    actual object Title3: PlatformTypography() {...}
}
e
Differs by platform. One looks like:
Copy code
public actual sealed class PlatformTypography : Typography() {
  public abstract val weight: FontWeight

  public actual object Title1 : PlatformTypography() {
    override val weight: FontWeight = FontWeight.Regular
  }

  ...
}
And another looks like:
Copy code
public actual sealed class PlatformTypography(
  public val weight: FontWeight,
  public val size: Px
) : Typography() {
  public abstract val weight: FontWeight

  public actual object Title1 : PlatformTypography(
    weight = FontWeight.Regular,
    size = 34.px
  )

  ...
}
Looks like this should be possible.
e
Yeah, I think I'm going to file something on youtrack for this
After doing some searching in YouTrack it looks like different source sets are considered different modules. Mystery solved 😢
253 Views