
- Scala - Home
- Scala - Overview
- Scala - Features
- Scala - Environment Setup
- Scala - Build Tool (SBT)
- Scala - REPL
- Scala - Dot & Dotty
- Scala - Basic Syntax
- Scala - Hello World Program
- Scala - Identifiers
- Scala - Keywords
- Scala - Comments
- Scala - Code Blocks
- Scala - Semicolon
- Scala - Constructs
- Scala - Expressions
- Scala - Input and Output
- Scala - Optional Braces
- Scala - Underscore (_)
- Data Types and Variables
- Scala - Data Types
- Scala - Type Bounds
- Scala - Context Bound
- Scala - Variances
- Scala - Type Hierarchy
- Scala - Variables
- Scala - Variable Scopes
- Scala - Literals
- Scala - Numeric Types
- Scala - Boolean Types
- Scala - Char Type
- Scala - Unit Types
- Scala - Strings
- Scala - Arrays
- Scala - Null Type
- Scala - Nothing
- Scala - Any Type
- Scala - AnyRef Type
- Scala - Unified Types
- Scala - Dates and Times
- Scala - Ranges
- Scala - Multidimensional Arrays
- Scala - WrappedArray
- Scala - StringBuilder
- Scala - String Interpolation
- Scala - StringContext
- Scala - Type Casting
- Scala var vs val
- Scala Operators
- Scala - Operators
- Scala - Rules for Operators
- Scala - Arithmetic Operators
- Scala - Relational Operators
- Scala - Logical Operators
- Scala - Bitwise Operators
- Scala - Assignment Operators
- Scala - Operators Precedence
- Scala - Symbolic Operators
- Scala - Range Operator
- Scala - String Concatenation Operator
- Scala Conditional Statements
- Scala - IF ELSE
- Scala - IF-ELSE-IF-ELSE Statement
- Scala - Nested IF-ELSE Statement
- Scala Loop Statements
- Scala - Loop Statements
- Scala - while Loop
- Scala - do-while Loop
- Scala - Nested Loops
- Scala - for Loop
- Scala - break Statement
- Scala - yield Keyword
- Scala Classes & Objects
- Scala - Classes & Objects
- Scala - Constructors
- Scala - Auxiliary Constructor
- Scala - Primary Constructor
- Scala - This Keyword
- Scala - Nested Classes
- Scala - Getters and Setters
- Scala - Object Private Fields
- Scala - Singleton Object
- Scala - Companion Objects
- Scala - Creating Executable Programs
- Scala - Stateful Object
- Scala - Enumerations
- Scala - Polymorphism
- Scala - Access Modifiers
- Scala - Apply Method
- Scala - Update Methods
- Scala - UnapplySeq Method
- Scala - Inheritance
- Scala - Extending a Class
- Scala - Method Overloading
- Scala - Method Overriding
- Scala - Generic Classes
- Scala - Generic Functions
- Scala - Superclass Construction
- Scala Methods & Functions
- Scala - Functions
- Scala - Main Methods
- Scala - Functions Call-by-Name
- Scala - Functions with Named Arguments
- Scala - Function with Variable Arguments
- Scala - Recursion Functions
- Scala - Default Parameter Values
- Scala - Functions without Parameters
- Scala - Implicit Parameters
- Scala - Higher-Order Functions
- Scala - Nested Functions
- Scala - Extension Methods
- Scala - Anonymous Functions
- Partially Applied Functions
- Scala - Lazy Val
- Scala - Pure Function
- Scala - Currying Functions
- Scala - Control Abstractions
- Scala - Corecursion
- Scala - Unfold
- Scala - Tail Recursion
- Scala - Infinite Sequences
- Scala - Dynamic Invocation
- Scala - Lambda Expressions
- Scala Collections
- Scala - Collections
- Mutable and Immutable Collections
- Scala - Lists
- Scala - Sets
- Scala - Maps
- Scala - TreeMap
- Scala - SortedMap
- Scala - Tuples
- Scala - Iterators
- Scala - Options
- Scala - Infinite Streams
- Scala - Parallel Collections
- Scala - Algebraic Data Types
- Scala Pattern Matching
- Scala - Pattern Matching
- Scala - Type Patterns
- Scala - Exception Handling
- Scala - Extractors
- Scala - Regular Expressions
- Scala Files I/O
- Scala - Files I/O
- Scala Advanced Concepts
- Scala - Closures
- Scala - Futures
- Scala - Promises
- Scala - Traits
- Scala - Trait Mixins
- Scala - Layered Traits
- Scala - Trait Linearization
- Scala - Sealed Traits
- Scala - Transparent Traits
- Scala - Literal Type Arithmetic
- Scala - Inline keyword
- Scala - Def, Var & Val
- Scala - Dropped Features
- Scala - BDD Testing
Scala - Sealed Trait
Scala sealed traits allow you to restrict which classes can extend a trait. When a trait is marked as sealed, all of its subclasses must be defined in the same file as the sealed trait. This ensures that all possible subclasses are known at compile time, enabling exhaustive pattern matching and providing additional compile-time safety.
Defining a Sealed Trait
A sealed trait is defined just like a regular trait but uses the sealed keyword. Below is the syntax to define a sealed trait −
sealed trait Shape case class Circle(radius: Double) extends Shape case class Rectangle(length: Double, breadth: Double) extends Shape case class Square(side: Double) extends Shape
Example of a Sealed Trait
In this example, we define a sealed trait Shape and three case classes Circle, Rectangle, and Square that extend Shape. All subclasses must be in the same file.
sealed trait Shape case class Circle(radius: Double) extends Shape case class Rectangle(length: Double, breadth: Double) extends Shape case class Square(side: Double) extends Shape object Demo { def describe(shape: Shape): String = shape match { case Circle(radius) => s"A circle with radius $radius" case Rectangle(length, breadth) => s"A rectangle with length $length and breadth $breadth" case Square(side) => s"A square with side $side" } def main(args: Array[String]): Unit = { val shapes: List[Shape] = List(Circle(5.0), Rectangle(2.0, 3.0), Square(4.0)) shapes.foreach { shape => println(describe(shape)) } } }
Save the above program in Demo.scala. The following commands are used to compile and execute this program.
Command
\>scalac Demo.scala \>scala Demo
The output will be −
A circle with radius 5.0 A rectangle with length 2.0 and breadth 3.0 A square with side 4.0
Usage of Sealed Traits
Sealed traits are particularly useful for defining closed hierarchies where all possible subclasses are known. This allows the compiler to check for exhaustive pattern matching, improving code safety and reliability.
Example
sealed trait Status case object Success extends Status case class Failure(reason: String) extends Status object Demo { def getStatusMessage(status: Status): String = status match { case Success => "Operation was successful" case Failure(reason) => s"Operation failed: $reason" } def main(args: Array[String]): Unit = { val statuses: List[Status] = List(Success, Failure("Invalid input")) statuses.foreach { status => println(getStatusMessage(status)) } } }
In this example, the sealed trait Status has two subclasses, Success and Failure. The pattern matching in getStatusMessage is exhaustive, covering all possible cases.
Save the above program in Demo.scala. The following commands are used to compile and execute this program.
Command
\>scalac Demo.scala \>scala Demo
The output will be −
Operation was successful Operation failed: Invalid input
Advanced Example with Sealed Traits
To further illustrate the power of sealed traits, let's consider a more complex example involving nested sealed traits.
Example
sealed trait Animal sealed trait Mammal extends Animal case class Dog(name: String) extends Mammal case class Cat(name: String) extends Mammal sealed trait Bird extends Animal case class Sparrow(name: String) extends Bird case class Parrot(name: String) extends Bird object Demo { def describe(animal: Animal): String = animal match { case Dog(name) => s"A dog named $name" case Cat(name) => s"A cat named $name" case Sparrow(name) => s"A sparrow named $name" case Parrot(name) => s"A parrot named $name" } def main(args: Array[String]): Unit = { val animals: List[Animal] = List(Dog("Buddy"), Cat("Whiskers"), Sparrow("Jack"), Parrot("Polly")) animals.foreach { animal => println(describe(animal)) } } }
Save the above program in Demo.scala. The following commands are used to compile and execute this program.
Command
\>scalac Demo.scala \>scala Demo
The output will be −
A dog named Buddy A cat named Whiskers A sparrow named Jack A parrot named Polly
Sealed Trait Summary
- Traits are used to compose behavior in Scala. Sealed traits allow the compiler to ensure that pattern matching is exhaustive and to cover all possible subclasses.
- Sealed traits provide additional compile-time safety and make the code easier to reason about by restricting the subclasses to the same file
- Sealed traits are ideal for defining closed hierarchies where all possible subclasses are known and fixed.
- You can use sealed traits to improve code readability and maintainability by making it clear which classes belong to a particular hierarchy.
- While sealed traits restrict the addition of new subclasses, these can still be extended by adding new case classes or objects within the same file.