In Scala 3, all kinds of definitions can be written at the “top level” of your source code files. For instance, you can create a file named MyCoolApp.scala and put these contents into it:
import scala.collection.mutable.ArrayBuffer
enum Topping:
case Cheese, Pepperoni, Mushrooms
import Topping.*
class Pizza:
val toppings = ArrayBuffer[Topping]()
val p = Pizza()
extension (s: String)
def capitalizeAllWords = s.split(" ").map(_.capitalize).mkString(" ")
val hwUpper = "hello, world".capitalizeAllWords
type Money = BigDecimal
// more definitions here as desired ...
@main def myApp =
p.toppings += Cheese
println("show me the code".capitalizeAllWords)
As shown, there’s no need to put those definitions inside a package
, class
, or other construct.
Replaces package objects
If you’re familiar with Scala 2, this approach replaces package objects. But while being much easier to use, they work similarly: When you place a definition in a package named foo, you can then access that definition under all other packages under foo, such as within the foo.bar package in this example:
package foo {
def double(i: Int) = i * 2
}
package foo {
package bar {
@main def fooBarMain =
println(s"${double(1)}") // this works
}
}
Curly braces are used in this example to put an emphasis on the package nesting.
The benefit of this approach is that you can place definitions under a package named com.acme.myapp, and then those definitions can be referenced within com.acme.myapp.model, com.acme.myapp.controller, etc.
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
- String Interpolation
- Control Structures
- Domain Modeling
- Tools
- OOP Modeling
- FP Modeling
- Methods
- Method Features
- Main Methods in Scala 3
- Summary
- Functions
- Anonymous Functions
- Function Variables
- Partial Functions
- 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
- Context Parameters
- 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