
- 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 - Methods
- Scala - Functions
- Scala - Methods vs 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 - Polymorphic Functions
- 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 - NumericRange
- Scala - Infinite Streams
- Scala - Parallel Collections
- Scala Advanced Types
- Scala - Union Types
- Scala - Intersection Types
- Scala - Type Aliases
- Scala - Structural Types
- Scala - Match Expression
- Scala - Singleton Type Operator
- Scala - Abstract Types
- Scala - Dependent Types
- Scala - Abstract Type Bounds
- Scala - Higher-Kinded Types
- Scala - Opaque Type Alias
- Scala - Path-Dependent Types
- Scala - Type Lambdas
- Scala - Type Inference
- Scala - Algebraic Data Types
- Scala Pattern Matching
- Scala - Pattern Matching
- Scala - Guards
- Scala - Variables in Patterns
- Scala - Type Patterns
- Scala - The Matchable Trait
- Scala - Matching Arrays
- Scala - Matching Lists
- Scala - Matching Tuples
- Scala - Exception Handling
- Scala - Extractors
- Scala - Pattern Bindings
- Scala - Regular Expressions
- Scala - Case Classes
- Scala - Partial Functions
- Scala - Packaging and Imports
- Scala - Implicit Imports
- Scala - Export Clauses
- Scala - Nested Packages
- Scala - Chained Packages
- Scala - Package Objects
- Scala Files I/O
- Scala - Files I/O
- Scala - Writing Files
- Scala - Listing Files
- Scala - Deleting Directories
- Scala - Check File Exists
- 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 - Process Management
- Scala - Scaladoc
- Scala - Literal Type Arithmetic
- Scala - Inline keyword
- Scala - Def, Var & Val
- Scala - Dropped Features
- Scala Unit Testing
- Scala - Unit Testing
- Scala - uTest
- Scala - MUnit
- Scala - ScalaTest Runner
- Scala - ScalaMock
- Scala - JUnit
- Scala - Mocking
- Scala - BDD Testing
Scala - Case Classes
Case class in Scala is used to define objects that are public and immutable by default. There are many built-in methods available in case class. You have to use case keywords to define case class and object in Scala.
Case Classes apply, unapply, and copy Methods
Case class has several methods, like apply and unapply. The apply method acts as constructor and the unapply method provides pattern matching. You can use the apply method to create instances of a case class. You can use the unapply method to decompose instances during pattern matching. Case class also has a copy method that creates copies and modifies instances.
Syntax
The syntax of the case classes in Scala -
case class Person(name: String, age: Int)
Here, the case class Person is defined with two fields: name and age. So, the compiler generates apply method for creating instances. The unapply method is used for pattern matching.
Example
Try the following example program of the Person case class -
case class Person(name: String, age: Int) object Demo { def main(args: Array[String]) = { val person = Person("Zara", 25) // Using the apply method to create an instance println(s"Created person: $person") // Using the unapply method for pattern matching person match { case Person(name, age) => println(s"Name: $name, Age: $age") case _ => println("Not a person") } // Using the copy method to create a modified copy val olderPerson = person.copy(age = 30) println(s"Older person: $olderPerson") } }
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
Created person: Person(Zara,25) Name: Zara, Age: 25 Older person: Person(Zara,30)
Pattern Matching with Case Classes
You can work with pattern matching using case classes. You can decompose and match instances easily. The unapply method is automatically generated and extracts the fields of case class during pattern matching.
We will define a case class Person. We will use pattern matching to decompose instances of the case class.
Syntax
case class Person(name: String, age: Int) def greet(person: Person) = person match { case Person(name, age) if age < 18 => s"Hello, $name! You're a minor." case Person(name, age) => s"Hello, $name!" }
Example
Try the following example program of pattern matching with a case class -
case class Person(name: String, age: Int) object Demo { case class Person(name: String, age: Int) def greet(person: Person) = person match { case Person(name, age) if age < 18 => s"Hello, $name! You're a minor." case Person(name, age) => s"Hello, $name!" } def main(args: Array[String]) = { val person1 = Person("Nuha", 16) val person2 = Person("Ayan", 21) println(greet(person1)) println(greet(person2)) } }
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
Hello, Nuha! You're a minor. Hello, Ayan!
In this example, there is greet function. It uses pattern matching for different cases based on the age of the Person.
Copying Case Class Instances
There is copy method that is built-in method of case class. You can modify copies of instances after copying these from original. This method is used to create new instances with some fields. So, you can change these fields and keep the rest unchanged.
Let us take an example of using the copy method with a case class. We will define a case class Person and use the copy method to create a modified copy of an instance.
Syntax
case class Person(name: String, age: Int) val person = Person("Maira", 25) val olderPerson = person.copy(age = 30)
Example
Try the following example program of copy method with a case class -
case class Person(name: String, age: Int) object Demo { case class Person(name: String, age: Int) def main(args: Array[String]) = { val person = Person("Maira", 25) println(s"Original person: $person") val olderPerson = person.copy(age = 30) println(s"Older person: $olderPerson") } }
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
Original person: Person(Maira,25) Older person: Person(Maira,30)
In this example, a copy method is used. It creates and then modifies copy of the Person instance with different age.
Equality and Hashing
Case classes have implementations of equals and hashCode methods based on the values of the fields. So, it is easy to compare instances and use these in collections that depend on hashing, like sets and maps.
Consider a case class Person and use equality and hashing with instances. Let us take an example of using equality and hashing with a case class. We will define a case class Person and compare instances for equality and use them in a set.
Syntax
case class Person(name: String, age: Int) val person1 = Person("Nuha", 25) val person2 = Person("Nuha", 25) val person3 = Person("Ayan", 30) println(person1 == person2) // true println(person1 == person3) // false val people = Set(person1, person2, person3) println(people)
Example
Try the following example program of equality and hashing with a case class -
case class Person(name: String, age: Int) object Demo { case class Person(name: String, age: Int) def main(args: Array[String]) = { val person1 = Person("Nuha", 25) val person2 = Person("Nuha", 25) val person3 = Person("Ayan", 30) println(person1 == person2) // true println(person1 == person3) // false val people = Set(person1, person2, person3) println(people) } }
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
true false Set(Person(Nuha,25), Person(Ayan,30))
In this example, there are equals and hashCode methods. These are used to compare instances of the Person case class and to store them in a set.
Case Objects
Case objects are similar to case classes but are used for singleton objects. Case objects have many common features of case classes. For example, both are serializable and have default hashCode implementation.
Consider a case object Employee. It has more features over regular objects. Let us take an example of using a case object. We will define a case object Employee.
Syntax
case object Employee { val name = "Zara" val age = 23 }
Example
Try the following example program of a case object -
case object Employee { val name = "Zara" val age = 23 } object Demo { case object Employee { val name = "Zara" val age = 23 } def main(args: Array[String]) = { println(s"Name of the employee is ${Employee.name}") println(s"Age of the employee is ${Employee.age}") } }
Save the above program in Demo.scala. Use the following commands to compile and execute this program.
Command
> scalac Demo.scala > scala Demo
Output
Name of the employee is Zara Age of the employee is 23
Difference Between Class and Case Class
The following table shows the key differences between class and case class −
Feature | Class | Case Class |
---|---|---|
Constructor Parameters | Private by default | Public and immutable by default |
Apply Method | Not available by default | Automatically generated |
Unapply Method | Not available by default | Automatically generated |
Pattern Matching | Not supported | Supported |
equals and hashCode | Must be defined manually | Automatically generated |
toString | Must be defined manually | Automatically generated |
Copy Method | Not available by default | Automatically generated |
Companion Object | Not generated automatically | Automatically generated |
Inheritance from Another Case Class | Supported | Not supported |
Case Classes Summary
- Case classes are used to define public and immutable
- Case classes also provide various in-built methods, like apply(), unapply(), copy(), etc.
- The apply method creates instances and unapply method is used for pattern matching.
- You can copy instances of case class using the copy method.
- You can decompose and match instances easily using case classes.
- Case classes have implementations of equals and hashCode methods based on the values of the fields.
- Case objects are similar to case classes but used for singleton objects.
- Scala compiler generates methods like apply, unapply, equals, hashCode, toString, and copy for case classes.