Interface GameEvent

All Known Implementing Classes:
GameEvent.CurrentPieceChanged, GameEvent.FrozenBlocksChanged, GameEvent.GameStateChanged, GameEvent.NextPieceChanged, GameEvent.RowsCleared

Sealed interface representing type-safe events for the Tetris game's PropertyChangeListener framework. This provides a modern, type-safe alternative to the string-based property constants defined in PropertyChangeEnabledGameControls.

Each implementing record represents a specific event that can be observed, carrying the actual event data for compile-time safety. This design enables pattern matching and exhaustiveness checking in switch expressions when handling game events.

Design Pattern: Sealed Classes + Records (Java 21)

  • Sealed interface ensures all event types are known at compile time
  • Record implementations provide immutability and reduced boilerplate
  • Pattern matching enables type-safe event handling without casting

Usage example with PropertyChangeListener:

game.addPropertyChangeListener(evt -> {
    if (evt.getNewValue() instanceof GameEvent event) {
        switch (event) {
            case GameEvent.GameStateChanged e ->
                handleStateChange(e.oldState(), e.newState());
            case GameEvent.CurrentPieceChanged e ->
                updateCurrentPiece(e.piece());
            case GameEvent.RowsCleared e ->
                handleRowsCleared(e.count());
            // compiler ensures all cases are handled
        }
    }
});
Version:
Autumn 2025
Author:
Charles Bryan
See Also:
  • Method Details

    • timestamp

      long timestamp()
      Returns the timestamp when this event was created.
      Returns:
      timestamp in milliseconds since epoch
    • getPropertyName

      default String getPropertyName()
      Returns the property name for this event type, used when registering property-specific listeners via PropertyChangeEnabledGameControls.addPropertyChangeListener(String, java.beans.PropertyChangeListener).

      This method provides a self-describing property name for each event type, enabling type-safe listener registration without hardcoded strings.

      Default Implementation: Returns the simple class name of the event (e.g., "GameStateChanged", "CurrentPieceChanged"). This ensures consistency between the event type and its property name.

      Usage Example:

      // Create an event
      GameEvent event = new GameEvent.GameStateChanged(oldState, newState, GameEvent.now());
      
      // Get its property name programmatically
      String propertyName = event.getPropertyName();  // Returns "GameStateChanged"
      
      // Use it to register a specific listener
      game.addPropertyChangeListener(
          new GameEvent.GameStateChanged(null, null, 0).getPropertyName(),
          evt -> handleStateChange(evt)
      );
      
      // Or more simply, use the string directly:
      game.addPropertyChangeListener("GameStateChanged", evt -> ...);
      

      Property Names by Event Type:

      Returns:
      the property name string for this event type
      See Also:
    • now

      static long now()
      Helper method to get the current time.
      Returns:
      current time in milliseconds since epoch