Scala Tutorial

Basics

Control Statements

OOP Concepts

Parameterized - Type

Exceptions

Scala Annotation

Methods

String

Scala Packages

Scala Trait

Collections

Scala Options

Miscellaneous Topics

Scala | Final

In Scala, the final keyword is used to prevent further inheritance or overriding. The use of final can apply to classes, methods, and fields:

  1. Final Classes: A class marked as final cannot be subclassed. This is useful when you want to ensure that there are no further specializations of a class.

    final class MyFinalClass {
      // class implementation
    }
    
    // This will result in a compilation error
    class AttemptedSubClass extends MyFinalClass {
      // some implementation
    }
    
  2. Final Methods: Within a class or trait, if a method is marked final, it cannot be overridden in subclasses. This is especially useful in traits, as it allows you to define behavior that subclasses cannot change.

    class ParentClass {
      final def myFinalMethod(): String = "This method cannot be overridden"
    }
    
    class ChildClass extends ParentClass {
      // This will result in a compilation error
      // override def myFinalMethod(): String = "Trying to override"
    }
    
  3. Final Fields (Vals and Vars): Fields marked as final cannot be overridden in subclasses. Note that a val is already immutable in terms of its content (though it can be overridden to provide a different initial value), but marking it final ensures it cannot be overridden at all.

    class ParentClass {
      final val myFinalVal: Int = 10
    }
    
    class ChildClass extends ParentClass {
      // This will result in a compilation error
      // override val myFinalVal: Int = 20
    }
    

Why use final?

  1. Immutable Behavior: Ensuring certain behaviors or properties of a class remain immutable, especially if changing them could introduce unintended side effects or break class invariants.

  2. Optimization: Some JVM optimizations can be more aggressive when the compiler knows a method can't be overridden.

  3. Design Intent: Indicate to other developers that a particular class, method, or field is in its final form and shouldn't be extended or modified.

In general, using final is a way to communicate and enforce design decisions about inheritance and overriding in your Scala code. It can ensure safety, clarity, and sometimes even performance benefits.

  1. Using 'final' for Variables and Methods in Scala:

    Applying final to a variable or method indicates that it cannot be overridden or reassigned.

    class Example {
      final val constantValue: Int = 42
    
      final def printMessage(): Unit = {
        println("This method cannot be overridden.")
      }
    }
    
  2. Final Classes and Objects in Scala:

    Declaring a class or object as final prevents it from being subclassed or extended.

    final class Singleton
    
    final object Utility
    
  3. Final Parameters in Scala:

    Marking parameters as final ensures they cannot be reassigned within the method.

    def processInput(final input: String): Unit = {
      // Code using input
    }
    
  4. Inheritance and 'final' in Scala:

    Applying final to a class prevents it from being extended, ensuring that the class hierarchy is not altered.

    final class BaseClass
    // Cannot extend BaseClass in a subclass
    
  5. Overriding Final Methods and Fields in Scala:

    Attempting to override a final method or field results in a compilation error.

    class Example extends BaseClass {
      // Compilation error: Cannot override a final method
      override def printMessage(): Unit = {
        println("Overridden method.")
      }
    }
    
  6. Immutability and 'final' in Scala:

    The use of final promotes immutability, making it clear that a variable, method, or class should not be modified or extended.

    final case class ImmutableData(value: Int)
    
    val data = ImmutableData(42)
    // Cannot modify 'data' as it is immutable