Skip to content

Instantly share code, notes, and snippets.

@udalov
Created March 28, 2016 11:31
Show Gist options
  • Save udalov/3c0d4a0f17eaf9ca2e2a to your computer and use it in GitHub Desktop.
Save udalov/3c0d4a0f17eaf9ca2e2a to your computer and use it in GitHub Desktop.

Revisions

  1. udalov created this gist Mar 28, 2016.
    89 changes: 89 additions & 0 deletions spec-sealed-data.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,89 @@
    # Summary

    Allow data classes as sealed class subclasses.
    ```
    sealed class Base {
    data class Derived(...) : Base()
    }
    ```

    # Motivation / use cases

    - Algebraic data types
    https://discuss.kotlinlang.org/t/sealed-classes-design/82
    http://stackoverflow.com/questions/35921234/kotlin-sealed-class-cannot-contain-data-classes-why

    # Description

    `data` modifier should now be allowed on subclasses of sealed classes.

    `componentN`, `equals`, `hashCode`, `toString`, `copy` are generated exactly as for usual data classes.
    Only primary constructor parameters of the data class itself should participate in all of those functions.

    ```
    sealed class Base(val sealedParam: Any?) {
    data class Derived(val dataParam: Any?) : Base(null)
    }
    fun test(d: Base.Derived) {
    val (x) = d // ok, x = d.dataParam
    val (x, y) = d // error, no component2 in Derived
    }
    ```

    <...>

    # Effort

    - Front-end: little
    - relax the diagnostic
    - improve some existing diagnostics: "data class cannot inherit from class" is no longer true
    - Back-end (JVM):
    - always generate equals/hashCode/toString for data classes (KT-6206)
    - Standard library: none
    - IDE: ???
    - Tools: none

    # Drawbacks

    None (?)

    # Open questions

    - Sealed class can have super-classes itself, will there be any problems with that?
    Consider sealed subclasses of sealed classes

    ```
    sealed class Base {
    data class Derived(val s: String) : Base()
    override fun toString() = "Base"
    }
    Base.Derived("ok").toString() // should return "Derived(s='ok')", not "Base"
    ```

    - For uniformity consider generating toString() to object declarations, similar to data classes (KT-4107)

    # Related issues

    Some issues were closed around 1.0 because data class inheritance had been forbidden. They should be located and investigated again wrt this proposal.

    - KT-11306: won't be able to e.g. specify abstract toString() in sealed class

    <...>

    # Alternatives

    We could support sealed interfaces. Some of the use cases will be covered because data classes can inherit from sealed interfaces.
    However, it's not possible to store data in an interface. Also it's possible to inherit such interface from Java, which would break exhaustive `when`s.

    # Possible future advancements

    - Allow data classes extend other classes?
    - Allow non-val/var (incl. vararg) trailing constructor parameters for data classes?

    # (???) Comparison to other languages?