Skip to content

Data-oriented programming: sealed + records + pattern matching switch - #102

Merged
mperor merged 1 commit into
masterfrom
DAILY/89-sealed-records-pattern-matching
Oct 25, 2026
Merged

mperor merged 1 commit into
masterfrom
DAILY/89-sealed-records-pattern-matching

Conversation

@mperor

@mperor mperor commented Oct 25, 2026 •

Copy link
Copy Markdown
Owner

What you'll learn

  • How a sealed interface plus a closed set of record implementations models data without inheritance tricks
  • How to deconstruct nested records directly in a switch with record patterns
  • How a when guard lets you special-case a pattern before falling back to the general one
  • Why a sealed hierarchy makes switch exhaustiveness a compile-time guarantee instead of a runtime hope

Why it matters

This combination (sealed types + records + pattern-matching switch) is the core of "data-oriented programming" in modern Java: it replaces instanceof/cast chains and the visitor pattern with exhaustive, compiler-checked switches, so adding a new case in the data model is caught immediately everywhere it's handled.

Read more

Quiz

Given

sealed interface Expr permits Const, Add, Mul {}
record Const(double value) implements Expr {}
record Add(Expr left, Expr right) implements Expr {}
record Mul(Expr left, Expr right) implements Expr {}

and eval switching with case Mul(Const c, Expr right) when c.value() == 0 -> 0; before the generic case Mul(Expr left, Expr right) -> eval(left) * eval(right); — does eval(new Mul(new Const(0), new Add(new Const(1), new Const(1)))) evaluate the Add branch?

AnswerNo. The guarded `Mul(Const c, Expr right) when c.value() == 0` pattern matches first and returns `0` immediately, so `eval` is never called on the `Add` subexpression — multiplying by a constant zero short-circuits without evaluating the other operand.

Note: this sandbox only has JDK 21 installed, and its network policy blocks both the Gradle toolchain auto-provisioner (foojay) and a direct JDK 25 download, so ./gradlew :FirstSteps:test could not be run locally for this PR. The code was reviewed carefully against the language spec; CI (which has JDK 25) will verify it compiles and passes. Marking as draft until that's confirmed.

Closes #89

@mperor mperor added the daily Queued for the daily learning PR label Oct 25, 2026
@github-actions

Copy link
Copy Markdown

Test Results

276 tests  +2   273 ✅ +2   6s ⏱️ ±0s
 80 suites +1     3 💤 ±0 
 80 files   +1     0 ❌ ±0 

Results for commit f486fcb. ± Comparison against base commit e635139.

This pull request skips 1 and un-skips 1 tests.
pl.mperor.lab.java.design.pattern.creational.singleton.SingletonTest ‑ testSerializationSafe()
pl.mperor.lab.java.design.pattern.creational.singleton.SingletonTest ‑ testThreadSafe()

@mperor
mperor marked this pull request as ready for review October 25, 2026 09:06
@mperor
mperor merged commit ae4119f into master Oct 25, 2026
2 checks passed
@mperor
mperor deleted the DAILY/89-sealed-records-pattern-matching branch October 25, 2026 09:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

daily Queued for the daily learning PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Data-oriented programming: sealed + records + pattern matching switch

1 participant