From 11b787842f8ad6e0e42e0cc68b66874eddbc3081 Mon Sep 17 00:00:00 2001 From: Bart Jacobs Date: Fri, 1 Dec 2023 16:38:08 +0100 Subject: [PATCH] Add closed_types.md to course text --- README.md | 2 ++ closed_types.md | 31 ++++++++++++++++++------------- latex.template | 5 +++++ make-pdf.sh | 2 ++ 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 99a0018..b46400f 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ - Concepts: interfaces, multiple inheritance, static fields, the Singleton pattern - [Implementation inheritance](implementation_inheritance.md) - Concepts: Inheritance of fields and methods, `super` constructor calls, `super` method calls +- [Closed types](closed_types.md) + - Concepts: types with a closed set of instances, enum classes, types with a closed set of direct subtypes, sealed types, switch statements and expressions - [Lists, sets, and maps](collections.md) - Concepts: the List, Set, and Map abstract datatypes (ADTs); the ArrayList, LinkedList, HashSet, and HashMap data structures; the Java Collections Framework diff --git a/closed_types.md b/closed_types.md index 30cefe2..334f3f3 100644 --- a/closed_types.md +++ b/closed_types.md @@ -14,7 +14,7 @@ public final class Score { public static final Score THIRTY = new Score(2, "THIRTY", 30); public static final Score FORTY = new Score(3, "FORTY", 40) { @Overrride - public Score next() { throw new UnsupportedOperationException("There is no next score"); } + public Score next() { throw new UnsupportedOperationException(); } }; private static final Score[] values = {LOVE, FIFTEEN, THIRTY, FORTY}; @@ -49,7 +49,7 @@ public enum Score { THIRTY(30), FORTY(40) { @Override - public Score next() { throw new UnsupportedOperationException("There is no next score"); } + public Score next() { throw new UnsupportedOperationException(); } }; private final int value; @@ -90,16 +90,21 @@ public String getScoreInFrench(Score score) { Consider an interface GameState whose instances are intended to represent the various states that a game of tennis can be in: ```java public interface GameState { - public record Regular(Score servingPlayerScore, Score receivingPlayerScore) implements GameState { - Regular { Objects.requireNonNull(servingPlayerScore); Objects.requireNonNull(receivingPlayerScore); } + public record Regular(Score serverScore, Score receiverScore) implements GameState { + Regular { + Objects.requireNonNull(serverScore); + Objects.requireNonNull(receiverScore); + } } - public record Advantage(boolean servingPlayer) implements GameState {} - public record Won(boolean servingPlayer) implements GameState {} + public record Advantage(boolean server) implements GameState {} + public record Won(boolean server) implements GameState {} } ``` We can prevent clients from defining additional classes that implement interface GameState by declaring it as *sealed*: ```java -public sealed interface GameState permits GameState.Regular, GameState.Advantage, GameState.Won { /* ... */ } +public sealed interface GameState + permits GameState.Regular, GameState.Advantage, GameState.Won +{ /* ... */ } ``` In this example, we can in fact just leave out the `permits` clause. This means only direct subtypes declared in the same file are allowed: ```java @@ -112,12 +117,12 @@ We can use switch statements or switch expressions to perform case analysis on a ```java public String toString(GameState state) { return switch (state) { - case GameState.Regular(var servingPlayerScore, var receivingPlayerScore) -> - servingPlayerScore.value() + "-" + receivingPlayerScore.value(); - case GameState.Advantage(var servingPlayer) -> - "advantage " + (servingPlayer ? "serving" : "receiving") + " player"; - case GameState.Won(var servingPlayer) -> - "won by the " + (servingPlayer ? "serving" : "receiving") + " player"; + case GameState.Regular(var serverScore, var receiverScore) -> + serverScore.value() + "-" + receiverScore.value(); + case GameState.Advantage(var server) -> + "advantage " + (server ? "server" : "receiver"); + case GameState.Won(var server) -> + "won by the " + (server ? "server" : "receiver"); }; } ``` diff --git a/latex.template b/latex.template index f797fe3..fb0fc1f 100644 --- a/latex.template +++ b/latex.template @@ -252,8 +252,13 @@ $if(listings)$ language=java, basicstyle=\ttfamily\footnotesize, commentstyle=\color{ogpjavadoc}\ttfamily\footnotesize, + morekeywords={enum,record,sealed,permits}, frame=lines, rulecolor=\color{black}} +\lstset{ + extendedchars=true, + literate={é}{{\'e}}1, +} %\lstset{xleftmargin=-2cm,xrightmargin=-2cm} $endif$ $if(lhs)$ diff --git a/make-pdf.sh b/make-pdf.sh index 4857b55..41e8eb9 100755 --- a/make-pdf.sh +++ b/make-pdf.sh @@ -17,6 +17,7 @@ pandoc -o course-notes.html -f gfm \ behavioral_subtyping.md \ interfaces.md \ implementation_inheritance.md \ + closed_types.md \ collections.md \ entity_relationship_abstractions.md \ multi_class_abstractions.md \ @@ -42,6 +43,7 @@ sed "${SED_IN_PLACE[@]}" \ -e 's/\\chapter{Behavioral subtyping: modular reasoning about programs that use dynamic binding}/\\chapter[Modular reasoning about dynamic binding]{Behavioral subtyping: modular reasoning about programs that use dynamic binding}/' \ -e 's/\\section{Modular reasoning about programs that use dynamic binding}/\\section[Modular reasoning about dynamic binding]{Modular reasoning about programs that use dynamic binding}/' \ -e 's/\\chapter{Iterators}/\\part{Part IV: Advanced Topics}\\chapter{Iterators}/' \ + -e 's/language=Java/language=Java,morekeywords={enum,record,sealed,permits}/g' \ course-notes.tex pdflatex course-notes.tex pdflatex course-notes.tex