0Pricing
Scala for Backend Engineering & Functional Programming · Lesson

Generics and Type Parameters

Understand how to write generic classes and methods to create reusable components with type safety.

What are Generics?

Imagine you need to create a container that can hold any type of item, like a String, an Int, or a custom object. Without generics, you'd either write a separate container for each type, leading to repetitive code, or use a very broad type like Any.

Generics allow you to write flexible, reusable code that works with various data types while still providing type safety at compile time. It's like a blueprint where you can plug in different materials later!

The `Any` Type Trap

Using Any as a placeholder for types can lead to problems. While it allows you to store anything, you lose the specific type information. This means you often need to cast the item back to its original type, which is error-prone and can cause runtime crashes if the cast is incorrect.

Try running this example and consider the potential issues:

class ItemHolder(val item: Any)

object Main {
  def main(args: Array[String]): Unit = {
    val stringHolder = new ItemHolder("Hello Scala")
    val numberHolder = new ItemHolder(123)

    // We need to cast, and it's unsafe if we get it wrong
    val retrievedString = stringHolder.item.asInstanceOf[String]
    println(s"Retrieved String: $retrievedString")

    // If we uncomment the line below, it compiles but will crash at runtime!
    // val wrongType = numberHolder.item.asInstanceOf[String]
    // println(s"Wrong Type: $wrongType")
  }
}

All lessons in this course

  1. Generics and Type Parameters
  2. Variance: Covariance & Contravariance
  3. Type Classes and Implicits
← Back to Scala for Backend Engineering & Functional Programming