Final specification for sealed class hierarchies, additional words about sealed when optimization
This commit is contained in:
@@ -5,7 +5,41 @@ Goals:
|
||||
|
||||
## Discussion
|
||||
|
||||
One option would be to make `when` understand hierarchies like this one:
|
||||
### Sealed Class Option
|
||||
|
||||
**This option is chosen as final.**
|
||||
|
||||
Special `sealed` keyword is introduced to mark base classes for sealed hierarchies, like this:
|
||||
|
||||
``` kotlin
|
||||
sealed class Type () {
|
||||
class Named(val name: String) : Type()
|
||||
class Nested {
|
||||
class Function(val param: Type, val result: Type): Type()
|
||||
}
|
||||
object Top: Type()
|
||||
}
|
||||
// ...
|
||||
when (type) {
|
||||
is Named -> println(name)
|
||||
is Nested.Function -> println("$param -> $result")
|
||||
// Alternatively, we can omit is here
|
||||
is Top -> println("TOP")
|
||||
}
|
||||
```
|
||||
|
||||
It's assumed here that sealed class can be subclassed only by nested classes or objects, both with any level of nesting,
|
||||
but not by local classes of any sort. So the `when` example would operate correctly.
|
||||
|
||||
Sealed classes are abstract by default, so abstract modifier is redundant
|
||||
(otherwise `when` requires additional case covering all other cases: is Type).
|
||||
Sealed classes can never be open or final.
|
||||
Sealed interfaces are prohibited, otherwise Java classes could easily inherit them.
|
||||
Sealed objects are also not possible, because we cannot inherit from object.
|
||||
|
||||
### Private Constructor Option
|
||||
|
||||
Another option would be to make `when` understand hierarchies like this one:
|
||||
|
||||
``` kotlin
|
||||
abstract class Type private () {
|
||||
@@ -24,6 +58,21 @@ when (type) {
|
||||
is Function -> println("$param -> $result")
|
||||
is Top -> println("TOP")
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
However, class with a private constructor can also be derived as a local class, that provides a problem for this option implementation.
|
||||
|
||||
## Future When Optimization
|
||||
|
||||
It's possible to optimize when on sealed in the way like when on enum or when on string.
|
||||
There are the following opportunities, all of them use `KSealed` interface with some `final` identification method:
|
||||
|
||||
* use `ordinal()` method, which is implemented like enums, so the first descendant has an ordinal 0,
|
||||
second 1 and so on. When on sealed organized like when on enum. Drawback: reordering breaks client's code.
|
||||
* use `sealedName()` method returning a fully qualified class name of a direct sealed descendant.
|
||||
When on sealed organized like when on string. Drawback: extra efforts.
|
||||
* use `sealedId()` method returning a hash code of a direct sealed descendant fully qualified class name.
|
||||
Drawbacks: possible collisions, including an opportunity to rename some member and get hash code of another member,
|
||||
which breaks client's code in a dramatic way.
|
||||
|
||||
After optimization, `instanceof KSealed` should be checked at run-time before applying it.
|
||||
|
||||
Reference in New Issue
Block a user