You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2021/08/09 13:12:38 UTC

[groovy-website] branch asf-site updated: add sealed types to release notes

This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/groovy-website.git


The following commit(s) were added to refs/heads/asf-site by this push:
     new 3b970e3  add sealed types to release notes
3b970e3 is described below

commit 3b970e361f42b0f0d5a42887532c561bde2c9b8a
Author: Paul King <pa...@asert.com.au>
AuthorDate: Mon Aug 9 23:12:32 2021 +1000

    add sealed types to release notes
---
 site/src/site/releasenotes/groovy-4.0.adoc | 60 ++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/site/src/site/releasenotes/groovy-4.0.adoc b/site/src/site/releasenotes/groovy-4.0.adoc
index 94240a0..2c323be 100644
--- a/site/src/site/releasenotes/groovy-4.0.adoc
+++ b/site/src/site/releasenotes/groovy-4.0.adoc
@@ -270,6 +270,66 @@ Optional.of(switch(i) {
 })
 --------------------------------------
 
+[[Groovy4.0-sealed-types]]
+=== Sealed types
+
+Sealed classes and interfaces restrict which other classes or interfaces may extend or implement them.
+For further details, see (link:https://groovy.apache.org/wiki/GEP-13.html[GEP-13]) and the
+Groovy documentation.
+
+As a motivating example, sealed hierarchies can be useful when specifying
+Algebraic or Abstract Data Types (ADTs) as shown in the following example:
+
+[source,groovy]
+--------------------------------------
+import groovy.transform.*
+
+@Sealed interface Tree<T> {}
+@Singleton final class Empty implements Tree {
+    String toString() { 'Empty' }
+}
+@Canonical final class Node<T> implements Tree<T> {
+    T value
+    Tree<T> left, right
+}
+
+Tree<Integer> tree = new Node<>(42, new Node<>(0, Empty.instance, Empty.instance), Empty.instance)
+assert tree.toString() == 'Node(42, Node(0, Empty, Empty), Empty)'
+--------------------------------------
+
+Here we are using the annotation syntax.
+
+As another example, sealed types can be useful when creating enhanced enum-like hierarchies. Here is a weather example using the `sealed` keyword:
+
+[source,groovy]
+--------------------------------------
+sealed abstract class Weather { }
+class Rainy extends Weather { Integer rainfall }
+class Sunny extends Weather { Integer temp }
+class Cloudy extends Weather { Integer uvIndex }
+def threeDayForecast = [
+    new Rainy(rainfall: 12),
+    new Sunny(temp: 35),
+    new Cloudy(uvIndex: 6)
+]
+--------------------------------------
+
+==== Differences to Java
+
+* The `non-sealed` keyword (or `@NonSealed` annotation) isn't required to indicate that
+subclasses are open to extension. A future version of Codenarc may have a rule that allows
+Groovy developers who wish to follow that Java practice if they desire. Having said that,
+keeping restrictions on extension (by using `final` or `sealed`) will lead to more places
+where future type checking can check for exhaustive use of types (e.g. switch expressions).
+* Currently, Groovy adds an annotation (@Sealed) to sealed classes but doesn't write
+sealed information into the bytecode (_native_ sealed classes).
+This allows Groovy sealed classes to be used for JDK8+.
+A future version of Groovy will write such information into the bytecode when using a JDK &gt; 17 and setting the target bytecode level to 17+. This will allow Java compilers to respect sealed Groovy classes
+in integration scenarios. Groovy does read such information from Java classes on JDKs where it is available.
+* Java has requirements around classes within a sealed hierarchy being in the same module or
+same package. Groovy currently doesn't enforce this requirement but may do so in a future version.
+In particular, it is likely _native_ sealed classes (see previous dot point) will need this requirement.
+
 [[Groovy4.0-new-checkers]]
 === Built-in type checkers