Scala Tutorial

Basics

Control Statements

OOP Concepts

Parameterized - Type

Exceptions

Scala Annotation

Methods

String

Scala Packages

Scala Trait

Collections

Scala Options

Miscellaneous Topics

Abstract Classes in Scala

Abstract classes in Scala provide a mechanism for creating classes that cannot be instantiated, but can be subclassed. They can have both abstract (unimplemented) and concrete (implemented) members. Abstract classes are useful when you want to provide a base for other classes but want to prevent the instantiation of the base class itself.

Let's take a look at the key features and how to define and use abstract classes in Scala:

  1. Definition: An abstract class is defined using the abstract keyword. It may contain abstract as well as non-abstract methods.

    abstract class Animal {
      def speak: String  // Abstract method, no body
      def eat: String = "Eating"  // Concrete method
    }
    
  2. Abstract Members: In Scala, you don't need to use the abstract keyword for unimplemented methods. If a method doesn't have a body, it's abstract. Note that you also can have abstract fields in Scala.

    abstract class Shape {
      def area: Double  // Abstract field
      def perimeter: Double  // Abstract method
    }
    
  3. Instantiation: You cannot create an instance of an abstract class.

    val animal = new Animal  // This will throw a compile-time error
    
  4. Subclassing: Subclasses of an abstract class must provide definitions for all of its abstract members, unless the subclass is also declared as abstract.

    class Dog extends Animal {
      def speak: String = "Woof"
    }
    

    If you don��t implement the abstract methods in the subclass, then the subclass also needs to be marked abstract.

  5. Constructor: Abstract classes can have constructors. You can pass parameters to these constructors when creating an instance of a subclass.

    abstract class Person(name: String, age: Int) {
      def displayDetails: String = s"My name is $name and I am $age years old."
    }
    
    class Student(name: String, age: Int, grade: String) extends Person(name, age) {
      def showGrade: String = s"I am in $grade grade."
    }
    
  6. Trait vs Abstract Class: In Scala, apart from abstract classes, we also have traits which are similar but have some differences:

    • Traits cannot have constructor parameters.
    • A class can extend multiple traits but only one abstract class.
    • Typically, if you want to represent a "type of thing" you'd use an abstract class. If you want to represent a "behavior", you might use a trait.

In summary, abstract classes in Scala allow for a partial implementation of a class, where concrete subclasses fill in the missing parts. They're especially useful when you want to encapsulate common logic among a set of related classes while ensuring that some methods or fields are implemented by any concrete subclasses.

  1. Scala abstract vs. concrete classes:

    • Description: Abstract classes in Scala cannot be instantiated on their own and may contain abstract methods. Concrete classes, on the other hand, can be instantiated and provide concrete implementations for all methods.
    • Code Example:
      // Abstract class
      abstract class Animal {
        def sound(): String
      }
      
      // Concrete class
      class Dog extends Animal {
        def sound(): String = "Woof"
      }
      
      val dog: Animal = new Dog()
      
  2. Defining abstract methods in Scala:

    • Description: Abstract methods in Scala are declared without providing a body. Subclasses must provide concrete implementations for these methods.
    • Code Example:
      abstract class Shape {
        def area(): Double
      }
      
      class Circle(radius: Double) extends Shape {
        def area(): Double = Math.PI * radius * radius
      }
      
  3. Inheritance with abstract classes in Scala:

    • Description: Abstract classes in Scala can be used for inheritance. Subclasses extend the abstract class and provide concrete implementations for abstract methods.
    • Code Example:
      abstract class Vehicle {
        def start(): Unit
      }
      
      class Car extends Vehicle {
        def start(): Unit = println("Car starting...")
      }
      
  4. Abstract classes and traits in Scala:

    • Description: Traits in Scala are similar to abstract classes but cannot have constructor parameters. Traits are used to define interfaces or mix in additional behavior.
    • Code Example:
      trait Logger {
        def log(message: String): Unit
      }
      
      class ConsoleLogger extends Logger {
        def log(message: String): Unit = println(s"Log: $message")
      }
      
  5. Abstract classes vs. interfaces in Scala:

    • Description: In Scala, abstract classes can have constructor parameters, while interfaces (traits) cannot. Abstract classes can also contain concrete methods.
    • Code Example:
      abstract class Writer {
        def write(message: String): Unit
      }
      
      trait Emitter {
        def emit(message: String): Unit
      }
      
  6. Scala abstract class constructor:

    • Description: Abstract classes in Scala can have constructors, allowing them to accept parameters when instantiated by subclasses.
    • Code Example:
      abstract class Shape(val color: String) {
        def area(): Double
      }
      
      class Circle(radius: Double, color: String) extends Shape(color) {
        def area(): Double = Math.PI * radius * radius
      }
      
  7. Scala sealed abstract classes:

    • Description: A sealed abstract class restricts the inheritance of the class to the same file. It is often used in pattern matching to ensure exhaustiveness.
    • Code Example:
      sealed abstract class Result
      case class Success(message: String) extends Result
      case class Failure(reason: String) extends Result
      
  8. Implementing abstract classes in Scala:

    • Description: Subclasses in Scala implement abstract classes by providing concrete definitions for all abstract methods and, if needed, the constructor parameters.
    • Code Example:
      abstract class Printer {
        def print(content: String): Unit
      }
      
      class ConsolePrinter extends Printer {
        def print(content: String): Unit = println(content)
      }
      
  9. Abstract classes and type parameters in Scala:

    • Description: Abstract classes in Scala can have type parameters, allowing them to work with different types in a generic way.
    • Code Example:
      abstract class Container[T](value: T) {
        def getValue(): T = value
      }
      
      class Box[T](content: T) extends Container[T](content)
      
  10. Scala abstract class examples:

    • Description: Abstract classes can model real-world entities with common behavior shared among subclasses. For example, an abstract class Employee might have methods like calculateSalary.
    • Code Example:
      abstract class Employee(val name: String, val employeeId: Int) {
        def calculateSalary(): Double
      }
      
      class Manager(name: String, employeeId: Int, val bonus: Double) extends Employee(name, employeeId) {
        def calculateSalary(): Double = 50000 + bonus
      }
      
  11. Abstract classes in Scala hierarchy:

    • Description: Abstract classes can be part of a hierarchy where subclasses extend the abstract class, and further subclasses extend them.
    • Code Example:
      abstract class Shape {
        def area(): Double
      }
      
      class Circle(radius: Double) extends Shape {
        def area(): Double = Math.PI * radius * radius
      }
      
      class Square(side: Double) extends Shape {
        def area(): Double = side * side
      }