CS 3180 Mobile Application Development

Week 1: Kotlin Fundamentals

CS 3180 — Mobile Application Development

val · var · Null Safety · Data Classes · Golf-Flavored Code

Week 1 Wednesday: Kotlin Fundamentals
CS 3180 Mobile Application Development

Setup Status Check

Quick show of hands:

  • Android Studio installed and emulator running?
  • Installed but emulator not yet?
  • Still working on the install?

If you're stuck: see me after class or post in #setup-help

Week 1 Wednesday: Kotlin Fundamentals
CS 3180 Mobile Application Development

Kotlin Fundamentals

Week 1 Wednesday: Kotlin Fundamentals
CS 3180 Mobile Application Development

val vs var

val playerName = "Alice Chen"   // immutable — cannot be reassigned
var currentScore = 0             // mutable — can change

Rule of thumb: prefer val. Use var only when the value must change.

Week 1 Wednesday: Kotlin Fundamentals
CS 3180 Mobile Application Development

Type Inference

Kotlin infers types — you don't always have to write them

val playerName = "Alice Chen"    // inferred: String
val currentScore = 0             // inferred: Int
val holePar: Int = 4             // explicit — also fine

Types are still static and checked at compile time

Week 1 Wednesday: Kotlin Fundamentals
CS 3180 Mobile Application Development

String Templates

val hole = 7
val par = 4
val score = 5

println("Hole $hole: par $par")
println("Score: ${score - par} relative to par")
println("Player: ${playerName.uppercase()}")

Use $variable for simple values, ${expression} for anything more

Week 1 Wednesday: Kotlin Fundamentals
CS 3180 Mobile Application Development

Null Safety

Week 1 Wednesday: Kotlin Fundamentals
CS 3180 Mobile Application Development

Nullable Types

In Kotlin, null must be explicitly allowed

val score: Int = 5       // cannot be null — compiler enforced
val score: Int? = null   // nullable — the ? makes it optional

A player may not have finished a hole yet — Int? models that correctly

Week 1 Wednesday: Kotlin Fundamentals
CS 3180 Mobile Application Development

The Elvis Operator ?:

Handle null with a default value in one line

val score: Int? = null
val display = score ?: "—"   // display = "—" if score is null

val strokes: Int? = 3
val label = strokes ?: "Not recorded"   // label = "Not recorded" only if null

Read ?: as: "use the left side, or if null, use the right side"

Week 1 Wednesday: Kotlin Fundamentals
CS 3180 Mobile Application Development

Functions and Control Flow

Week 1 Wednesday: Kotlin Fundamentals
CS 3180 Mobile Application Development

Functions with Default Arguments

fun calculateRelativeToPar(score: Int, par: Int = 4): Int = score - par

// Calls:
calculateRelativeToPar(5)        // par defaults to 4, returns 1
calculateRelativeToPar(3, 3)     // par is 3, returns 0
calculateRelativeToPar(score = 6, par = 5)  // named args

Default arguments reduce overloads; named args improve readability

Week 1 Wednesday: Kotlin Fundamentals
CS 3180 Mobile Application Development

The when Expression

val relative = calculateRelativeToPar(score, par)

val label = when {
    relative <= -2 -> "Eagle or better"
    relative == -1 -> "Birdie"
    relative == 0  -> "Par"
    relative == 1  -> "Bogey"
    else           -> "+${relative}"
}

when is an expression — it returns a value

Week 1 Wednesday: Kotlin Fundamentals
CS 3180 Mobile Application Development

Ranges and Loops

// Count through 18 holes
for (hole in 1..18) {
    println("Hole $hole")
}

// Scramble teams: 4 players
for (playerIndex in 0 until 4) {
    println("Player ${playerIndex + 1}")
}

// Check if a score is valid
val score = 3
val isReasonable = score in 1..10
Week 1 Wednesday: Kotlin Fundamentals
CS 3180 Mobile Application Development

Data Classes and Domain Modeling

Week 1 Wednesday: Kotlin Fundamentals
CS 3180 Mobile Application Development

What Is a Data Class?

data class GolfPlayer(val name: String, val handicap: Int = 0)

One line gives you for free:

  • Constructor
  • toString() — prints field values
  • equals() and hashCode() — value-based comparison
  • copy() — create modified copies
Week 1 Wednesday: Kotlin Fundamentals
CS 3180 Mobile Application Development

The Golf Domain Model

data class GolfPlayer(
    val name: String,
    val handicap: Int = 0
)

data class HoleScore(
    val holeNumber: Int,
    val par: Int,
    val strokes: Int?       // null = hole not yet played
)

data class GolfTeam(
    val name: String,
    val players: List<GolfPlayer>
)
Week 1 Wednesday: Kotlin Fundamentals
CS 3180 Mobile Application Development

The copy() Function

val alice = GolfPlayer("Alice Chen", handicap = 5)

// Update handicap without mutating the original
val aliceUpdated = alice.copy(handicap = 4)

println(alice)         // GolfPlayer(name=Alice Chen, handicap=5)
println(aliceUpdated)  // GolfPlayer(name=Alice Chen, handicap=4)

copy() creates a new instance — the original is unchanged

Week 1 Wednesday: Kotlin Fundamentals
CS 3180 Mobile Application Development

Micro-Exercise

Week 1 Wednesday: Kotlin Fundamentals
CS 3180 Mobile Application Development

Pair Task: Friendly Score Display

Write a function that takes a nullable hole score and prints friendly text:

Hole 5: par 4 — Birdie (3 strokes)
Hole 7: par 3 — Not recorded yet
Hole 12: par 5 — Eagle or better (3 strokes)

Steps:

  1. Create a HoleScore with a null strokes field
  2. Use the Elvis operator to handle null
  3. Use a when expression to produce the label
  4. Print using string templates
Week 1 Wednesday: Kotlin Fundamentals
CS 3180 Mobile Application Development

Solution Walkthrough

fun describeHole(hole: HoleScore): String {
    val strokesText = hole.strokes?.let { "$it strokes" } ?: "Not recorded yet"
    val relative = hole.strokes?.let { it - hole.par }
    val label = when {
        relative == null  -> "Not recorded"
        relative <= -2    -> "Eagle or better"
        relative == -1    -> "Birdie"
        relative == 0     -> "Par"
        relative == 1     -> "Bogey"
        else              -> "+$relative"
    }
    return "Hole ${hole.holeNumber}: par ${hole.par}$label ($strokesText)"
}
Week 1 Wednesday: Kotlin Fundamentals
CS 3180 Mobile Application Development

Week 1 Recap

Concept Key Idea
val / var Prefer immutability
Type inference Static but concise
String templates $var and ${expr}
Null safety Int? vs Int, Elvis ?:
when Replaces if-else chains
Data classes Free equals, copy, toString
Week 1 Wednesday: Kotlin Fundamentals
CS 3180 Mobile Application Development

Friday: Lab 01

First Compose screen — displaying a scorecard

Before Friday: finish Android Studio install, read zyBook Ch. 2

Week 1 Wednesday: Kotlin Fundamentals

SPEAKER NOTES: Welcome to the first demo session. Today we write actual Kotlin. By end of class students will understand the language features they'll use every day in this course. All examples connect directly to the golf scoring domain — this isn't abstract syntax practice.

SPEAKER NOTES: Do this quickly — 2 minutes max. The goal is to know how many students can follow along hands-on today. Students without a working install can still follow the code on screen. Anyone completely stuck on setup should visit office hours before Friday's lab.

SPEAKER NOTES: Now the main event. Kotlin is a modern, expressive language. Students coming from Java will notice it's far less verbose. Students coming from Python will notice the static typing. Frame it as: "Kotlin was designed to fix Java's biggest pain points while keeping the parts that work."

SPEAKER NOTES: This is the first thing Kotlin beginners need to internalize. val is like a final variable in Java or a const in other languages. Most variables in a well-written Kotlin program are val. Ask: "Why would immutability be valuable in a scoring app?" — concurrent updates, predictability, easier testing.

SPEAKER NOTES: Students from Python sometimes think "inferred types = dynamic types." Clarify: Kotlin is 100% statically typed. The compiler knows the type of every variable — it just doesn't make you write it out when it's obvious. Explicit annotations are fine and sometimes make code clearer.

SPEAKER NOTES: String templates eliminate the + concatenation noise from Java. Walk through each line: simple variable reference with $, expression in braces with ${ }, and a method call inside ${ }. Ask students: what would the output of the second println be? Answer: "Score: 1 relative to par" — a bogey.

SPEAKER NOTES: Null safety is one of Kotlin's defining features. Tony Hoare called null references his "billion-dollar mistake" in other languages. Kotlin makes nullability explicit in the type system so you can't accidentally dereference null.

SPEAKER NOTES: The key insight: the type system tells you at a glance whether a value can be null. You never have to guess or check documentation. Int vs Int? is a contract enforced by the compiler. This eliminates an entire class of runtime crashes that plague Java and other languages.

SPEAKER NOTES: The name "Elvis operator" comes from the ?: shape looking like Elvis's hair. Walk through both examples. Ask: in a live tournament scorecard, when would a hole score be null? Answer: the team hasn't played that hole yet. The Elvis operator lets us display "—" cleanly rather than crashing.

SPEAKER NOTES: Moving from variables to functions. Kotlin functions have some nice features that Java lacks — default arguments, named arguments, and expression bodies. These make golf scoring logic clean and readable.

SPEAKER NOTES: The single expression body (= score - par) is idiomatic Kotlin for simple functions. No need for curly braces or a return statement. Default par of 4 reflects that most holes on a golf course are par 4. Named arguments at the call site make the intent clear — especially useful when two Int parameters could be confused.

SPEAKER NOTES: This is cleaner than a chain of if-else-if. The condition-less when form (no argument after "when") acts like a switch on Boolean expressions. Point out that it's an expression — the result is assigned to label. Ask: what does the label evaluate to when score is 2 on a par 4? Answer: "Eagle or better."

SPEAKER NOTES: 1..18 is an inclusive range — both endpoints included. 0 until 4 is exclusive of the upper bound — equivalent to 0..3. The in operator works for membership checks too, as shown in the last line. Golf context: 18 holes, 4-player scramble teams, scores typically 1–10 strokes per hole.

SPEAKER NOTES: Now we model the golf domain in Kotlin. Data classes are one of the language's best features — they eliminate boilerplate for simple model objects. We'll define the three core entities we'll use throughout the semester.

SPEAKER NOTES: Compare to Java: a Java equivalent would be 30+ lines with getters, constructor, equals, hashCode, and toString. Kotlin's data class is idiomatic for model objects that are essentially structured data. The default handicap = 0 means you can create a player with just a name.

SPEAKER NOTES: These three classes will appear throughout the semester. GolfPlayer represents an individual participant. HoleScore captures one hole's result — note strokes is nullable because teams may not have finished. GolfTeam groups players under a team name. Walk through each field and ask students what data type makes sense before revealing it.

SPEAKER NOTES: copy() is essential for working with immutable data. Instead of mutating an object, you create a new one with the changed fields. This is a core pattern in Jetpack Compose, which we'll see starting week 3. Ask: why is immutability valuable in a scoring app? Multiple screens might be reading team data simultaneously — a mutable object shared between them is a bug waiting to happen.

SPEAKER NOTES: Five minutes of hands-on work. Pair students up — one person types, the other navigates. This is the first time they'll write Kotlin in class.

SPEAKER NOTES: Give them 4 minutes to work, then live-code the solution together. Circulate while they work — common mistakes: forgetting the ? on the nullable type, using == null instead of ?: , not using an expression body on when. The solution naturally combines val/var, null safety, when, and string templates from today's lesson.

SPEAKER NOTES: Walk through line by line. The ?.let { } pattern: if strokes is not null, execute the lambda with it as the parameter; otherwise return null, and the ?: gives us the fallback string. This is idiomatic Kotlin null-safe chaining. relative follows the same pattern — null if not played, Int if played. The when handles both cases cleanly.

SPEAKER NOTES: Quick summary before dismissal. These six concepts are the foundation for everything else. Students who are shaky on any of them should read zyBook Chapter 2 before Friday's lab. The lab will use all of these features together.

SPEAKER NOTES: Close with anticipation for Friday. Lab 01 will take today's Kotlin data classes and display them in a real Compose UI. Remind students: if they don't have a working emulator by Friday they won't be able to complete the lab independently. Office hours and #setup-help are available.