Extension methods let you add methods to a type after the type is defined, i.e., they let you add new methods to closed classes.
For example, imagine that someone else has created a Circle
class:
case class Circle(x: Double, y: Double, radius: Double)
Now imagine that you need a circumference
method, but you can’t modify their source code.
Before the concept of term inference was introduced into programming languages, the only thing you could do was write a method in a separate class or object like this:
object CircleHelpers:
def circumference(c: Circle): Double = c.radius * math.Pi * 2
Then you’d use that method like this:
val aCircle = Circle(2, 3, 5)
// without extension methods
CircleHelpers.circumference(aCircle)
But with extension methods you can create a circumference
method to work on Circle
instances:
extension (c: Circle)
def circumference: Double = c.radius * math.Pi * 2
In this code:
Circle
is the type that the extension methodcircumference
will be added to- The
c: Circle
syntax lets you reference the variablec
in your extension method(s)
Then in your code you use circumference
just as though it was originally defined in the Circle
class:
aCircle.circumference
Import extension method
Imagine, that circumference
is defined in package lib
, you can import it by
import lib.circumference
aCircle.circumference
The compiler also supports you if the import is missing by showing a detailed compilation error message such as the following:
value circumference is not a member of Circle, but could be made available as an extension method.
The following import might fix the problem:
import lib.circumference
Discussion
The extension
keyword declares that you’re about to define one or more extension methods on the type that’s put in parentheses.
To define multiple extension methods on a type, use this syntax:
extension (c: Circle)
def circumference: Double = c.radius * math.Pi * 2
def diameter: Double = c.radius * 2
def area: Double = math.Pi * c.radius * c.radius
Contributors to this page:
Contents
- Introduction
- Scala Features
- Why Scala 3?
- A Taste of Scala
- Hello, World!
- The REPL
- Variables and Data Types
- Control Structures
- Domain Modeling
- Methods
- First-Class Functions
- Singleton Objects
- Collections
- Contextual Abstractions
- Toplevel Definitions
- Summary
- A First Look at Types
- Control Structures
- Domain Modeling
- Tools
- OOP Modeling
- FP Modeling
- Methods
- Method Features
- Main Methods in Scala 3
- Summary
- Functions
- Anonymous Functions
- Function Variables
- Eta Expansion
- Higher-Order Functions
- Write Your Own map Method
- Creating a Method That Returns a Function
- Summary
- Packaging and Imports
- Scala Collections
- Collections Types
- Collections Methods
- Summary
- Functional Programming
- What is Functional Programming?
- Immutable Values
- Pure Functions
- Functions Are Values
- Functional Error Handling
- Summary
- Types and the Type System
- Inferred Types
- Generics
- Intersection Types
- Union Types
- Algebraic Data Types
- Variance
- Opaque Types
- Structural Types
- Dependent Function Types
- Other Types
- Contextual Abstractions
- Extension Methods
- Given Instances and Using Clauses
- Context Bounds
- Given Imports
- Type Classes
- Multiversal Equality
- Implicit Conversions
- Summary
- Concurrency
- Scala Tools
- Building and Testing Scala Projects with sbt
- Worksheets
- Interacting with Java
- Scala for Java Developers
- Scala for JavaScript Developers
- Scala for Python Developers
- Where To Go Next