Last active
March 4, 2023 22:10
-
-
Save rjrjr/7dcd53458a66a788505f1aeeea2c760d to your computer and use it in GitHub Desktop.
Poor Man's Sealed Classes (visitor pattern)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* For Java developers all excited by and jealous of Kotlin's sealed classes. | |
* Do this when you wish you could put parameters on an enum. | |
*/ | |
public class PoorMan { | |
interface Event { | |
<T> T dispatch(EventHandler<T> handler); | |
} | |
interface EventHandler<T> { | |
T onEvent(ThingHappened event); | |
T onEvent(AnotherThingHappened event); | |
T onEvent(AThingWithParametersHappened event); | |
} | |
static final class ThingHappened implements Event { | |
static final ThingHappened INSTANCE = new ThingHappened(); | |
private ThingHappened() { | |
} | |
@Override public <T> T dispatch(EventHandler<T> handler) { | |
return handler.onEvent(this); | |
} | |
} | |
static final class AnotherThingHappened implements Event { | |
static final AnotherThingHappened INSTANCE = new AnotherThingHappened(); | |
private AnotherThingHappened() { | |
} | |
@Override public <T> T dispatch(EventHandler<T> handler) { | |
return handler.onEvent(this); | |
} | |
} | |
static final class AThingWithParametersHappened implements Event { | |
final String foo; | |
final String bar; | |
AThingWithParametersHappened(String foo, String bar) { | |
this.foo = foo; | |
this.bar = bar; | |
} | |
@Override public <T> T dispatch(EventHandler<T> handler) { | |
return handler.onEvent(this); | |
} | |
} | |
static void omgAnEvent(Event event) { | |
String whatHappened = event.dispatch(new EventHandler<String>() { | |
@Override public String onEvent(ThingHappened event) { | |
return "A Thing"; | |
} | |
@Override public String onEvent(AnotherThingHappened event) { | |
return "A Nother Thing"; | |
} | |
@Override public String onEvent(AThingWithParametersHappened event) { | |
return "Foo: " + event.foo + ", Bar: " + event.bar; | |
} | |
}); | |
System.out.println(whatHappened); | |
} | |
public static void main(String... args) { | |
omgAnEvent(ThingHappened.INSTANCE); | |
omgAnEvent(AnotherThingHappened.INSTANCE); | |
omgAnEvent(new AThingWithParametersHappened("FOOOOO!", "bar")); | |
} | |
} |
Updated to a) compile and b) add return values, to make this useful for pipelines.
@rjrj Why not make the interface event private? It can't be instantiated from outside the file then.
Please rename the file to JavaSealedClass.java
instead for code highlighting and better readability.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The
omgAnEvent
method illustrates what you do instead of awhen
/switch
statement.