Variables and Types
## Learning Objectives
- Understand val vs var declarations
- Master Scala's type system
- Learn type inference
- Work with lazy val
- Understand basic data types
## Variable Declarations
### val (Immutable)
```scala
val x: Int = 10
val name: String = "Scala"
val pi: Double = 3.14159
```
Once assigned, a `val` cannot be reassigned:
```scala
val x = 10
x = 20 // Error: reassignment to val
```
### var (Mutable)
```scala
var counter = 0
counter = counter + 1 // OK - var can be reassigned
```
### When to Use val vs var
Prefer `val` by default for immutability. Use `var` only when mutation is necessary.
## Type System
### Basic Types
| Type | Description | Example |
|------|-------------|---------|
| Byte | 8-bit signed integer | `val b: Byte = 127` |
| Short | 16-bit signed integer | `val s: Short = 32767` |
| Int | 32-bit signed integer | `val i: Int = 2147483647` |
| Long | 64-bit signed integer | `val l: Long = 9223372036854775807L` |
| Float | 32-bit floating point | `val f: Float = 3.14f` |
| Double | 64-bit floating point | `val d: Double = 3.14159` |
| Char | 16-bit Unicode character | `val c: Char = 'A'` |
| Boolean | true or false | `val flag: Boolean = true` |
| String | Sequence of characters | `val s: String = "Hello"` |
### String Operations
```scala
val str = "Hello, Scala"
// Concatenation
val greeting = "Hello" + " " + "World"
// String methods
str.length // 12
str.toUpperCase // HELLO, SCALA
str.toLowerCase // hello, scala
str.substring(0, 5) // Hello
str.contains("Scala") // true
// String interpolation
val name = "Alice"
val age = 30
println(s"Name: $name, Age: $age")
println(s"Next year: ${age + 1}")
// Raw string
val path = raw"C:\Users\test"
```
### Multi-line Strings
```scala
val poem = """
|Roses are red
|Violets are blue
|Scala is awesome
|And so are you
""".stripMargin
```
## Type Inference
Scala's compiler can infer types:
```scala
val x = 10 // Int inferred
val name = "Scala" // String inferred
val pi = 3.14159 // Double inferred
val flag = true // Boolean inferred
// Explicit vs inferred
val x: Int = 10 // Explicit
val y = 20 // Inferred as Int
```
### When to Use Explicit Types
- Public API declarations (methods, class fields)
- Type is not immediately obvious
- Required for compilation in some ambiguous cases
## Type Hierarchy
```text
Any
├── AnyVal (value types)
│ ├── Int, Long, Double, Float, Boolean, Char, Unit
│ └── Byte, Short
└── AnyRef (reference types)
├── String
├── List, Set, Map
├── Option, Try, Either
└── All Java/Scala classes
```
### Nothing and Null
- `Nothing` - Bottom type, no values
- `Null` - Subtype of all reference types
```scala
def error(message: String): Nothing = {
throw new Exception(message)
}
```
## Unit
`Unit` is Scala's equivalent of Java's void:
```scala
def printAndReturn(str: String): Unit = {
println(str)
}
val result: Unit = println("Hello")
```
## Numeric Operations
```scala
val a = 10
val b = 3
// Arithmetic
a + b // 13
a - b // 7
a * b // 30
a / b // 3 (integer division)
a % b // 1
// Floating point
val c = 10.0
val d = 3.0
c / d // 3.333...
c % d // 1.0
// Type conversions
val intToDouble: Double = a // 10.0
val doubleToInt: Int = c.toInt // 10
```
## Characters and Booleans
```scala
// Characters
val c1: Char = 'A'
val c2: Char = '\u0041' // Unicode
val c3: Char = '\n' // Newline
// Boolean
val isScalaFun = true
val isJavaFun = false
// Boolean operations
!isScalaFun // false
isScalaFun && isJavaFun // false
isScalaFun || isJavaFun // true
```
## lazy val
`lazy val` is evaluated only when first accessed:
```scala
lazy val expensiveComputation = {
println("Computing...")
Thread.sleep(1000)
42
}
println("Before")
println(expensiveComputation) // Computing... then 42
println(expensiveComputation) // Just 42 (no recomputation)
```
### When to Use lazy val
- Expensive computations
- Resources that might not be needed
- Circular dependencies
## Type Aliases
```scala
type Matrix = List[List[Double]]
def invert(matrix: Matrix): Matrix = {
// Matrix operations
matrix
}
```
## Regex and Pattern Matching on Types
```scala
val numberPattern = "^[0-9]+$".r
"123" match {
case numberPattern() => println("It's a number!")
case _ => println("Not a number")
}
```
## Tuples
Tuples group heterogeneous values:
```scala
val person: (String, Int, Boolean) = ("Alice", 30, true)
// Access by index (1-based)
person._1 // Alice
person._2 // 30
person._3 // true
// Tuple pattern matching
val (name, age, isStudent) = person
```
## Summary
- `val` creates immutable bindings; `var` creates mutable ones
- Scala has Byte, Short, Int, Long, Float, Double, Char, Boolean, String, Unit
- Type inference reduces verbosity
- `lazy val` defers evaluation until first access
- Everything is an object, including basic types
- Tuples group heterogeneous values
- Prefer immutability (val) over mutability (var)
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →