Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Scala 3 Module 3

Domain modelling: classes, traits, case classes and enums interview questions

Interview questions on “Domain modelling: classes, traits, case classes and enums”: warm-ups, then what each harder question tests and how a good answer starts.

18 questions: 6 warm-ups and 12 with model answers · Levels: Fresher to senior

Warm-up questions

Short questions with short answers, each answered in full.

  1. Fresher

    What is a companion object in Scala, and what is it used for?

    Answered in the lesson Classes, objects and companion objects

  2. Fresher

    What is the difference between a trait and an abstract class in Scala 3?

    Answered in the lesson Traits, mixins and linearization

  3. Fresher

    What does the compiler generate for a case class?

    Answered in the lesson Case classes and immutable data

  4. Fresher

    What is an algebraic data type, and how do you write one in Scala 3?

    Answered in the lesson Enums, sealed traits and ADTs

  5. Fresher

    What is an extractor object in Scala?

    Answered in the lesson Scala 3 pattern matching in depth

  6. Fresher

    What is an opaque type in Scala 3, and how is it different from a type alias?

    Answered in the lesson Opaque types and value classes

Questions with model answers

What each question tests, the first step of a good answer and the follow-ups to expect.

  1. Fresher to senior

    A payments service has a Money class with a public constructor and a validate method that callers are meant to run first. Invalid amounts still reach the database every few weeks. How would you redesign the class so that an invalid Money cannot exist, and what would you check before rolling the change out?

    What it tests
    Private constructors behind a companion factory, Either for expected failures, immutability, and where Scala's private stops protecting a class: Java callers, reflection-based libraries and copies.
    First step
    Say why the bug keeps coming back: a public constructor lets every caller build a Money and forget validate. Make the constructor private and move the checks into a factory in the companion that returns Either[String, Money], so the type tells each caller that the call can fail and why.
    Follow-ups

    From the lesson Classes, objects and companion objects

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page.

    Opening the model answers with your pass…

    Model answers open with any MySmartCoPilot pass.

    • Pro pass · 1 week₹79$2.99
    • 30 days₹179$5.99
    • 1 year₹1,699$45

    One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

    It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  2. Mid to senior

    Your team publishes a library with a plain class RateCalculator. A client team extended it in their own code and overrode one method. After an internal refactor of yours, their subclass gives wrong totals, with no compile error anywhere. What went wrong, and how would you declare your library's classes from now on?

    What it tests
    The fragile base class problem, the extension contract that open documents, final for classes not designed for subclassing, ad hoc extensions and how to find them with -source future, and composition as the alternative.
    First step
    Explain the mechanism: the refactor changed which of the class's own methods call the overridden one, so the client's override now runs at another moment or not at all. Nothing in the declaration said the class was designed for subclassing, because it was neither open nor final.
    Follow-ups

    From the lesson Classes, objects and companion objects

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  3. Mid to senior

    A checkout class mixes in two traits, FraudCheck and Audit, that both override process and call super.process. In a clean-up, a teammate swapped their order in the extends clause, and audit records are now written before the fraud check runs. Explain what changed, and how you would make the order hard to get wrong.

    What it tests
    Linearization and the order of stacked super calls, why reordering mixins changes behaviour without any compile error, and safer designs: tests of the order, explicit composition, one trait that fixes the sequence.
    First step
    Write out the linearization before and after the swap: the last trait written runs first, and each super call moves one step to the left. Swapping the two traits swapped which wrapper starts first and which finishes last, and the compiler had no reason to complain.
    Follow-ups

    From the lesson Traits, mixins and linearization

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  4. Fresher to senior

    A shared trait computes val description = s"limit $limit" from an abstract val limit that each account class defines. In production the logs show limit 0 for every kind of account, although each class sets its own limit. Why does this happen, how do you fix it, and how do you stop the same bug elsewhere?

    What it tests
    The order in which traits and classes are set up, JVM zero values, trait parameters, lazy val and def as fixes, and the -Wsafe-init checker in CI.
    First step
    Explain the order of set-up: the trait's body runs before the class body, so description is computed while limit still holds the zero value, and as a val it never changes. Then pick a fix that either passes limit in before the trait runs or computes description after the class is set up.
    Follow-ups

    From the lesson Traits, mixins and linearization

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  5. Fresher to senior

    An order service puts Order case classes into a Set to drop duplicates before it writes a daily report, but the same order still appears two or three times. Order has a field tags: Array[String]. Explain why the Set keeps the duplicates, how you would fix it, and what else this field type puts at risk.

    What it tests
    How the generated equals and hashCode depend on each field's own equality, why arrays compare by reference, and choosing immutable collections for data types.
    First step
    Follow the generated equals: it compares every field with that field's own equals, and an Array's equals is reference equality. Two orders read separately hold two different arrays, so they are never equal and their hash codes differ, and the Set keeps both.
    Follow-ups

    From the lesson Case classes and immutable data

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  6. Mid to senior

    case class Discount(percent: Int) has a companion apply that rejects values above 100, yet discounts of 150 % keep reaching the database. How can such values be built, and how do you make the check impossible to skip in Scala 3?

    What it tests
    The generated methods that build a case-class value without apply, private constructors closing copy and apply in Scala 3, factories that return Either, and the paths outside the Scala compiler.
    First step
    List every way a Discount can be built: the custom apply checks its argument, but new Discount(150) calls the public constructor directly, and copy(percent = 150) on any valid Discount calls it too. The check guards one door out of three.
    Follow-ups

    From the lesson Case classes and immutable data

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  7. Fresher to senior

    A teammate wants to store each payment's status as Status.ordinal in a small integer column, to save space. What could go wrong over the next year, what would you store instead, and how would you move rows that already hold ordinals?

    What it tests
    What an ordinal is, why it changes when cases are added or reordered, stable encodings for enums, and a safe migration of stored data.
    First step
    Say what an ordinal is: the position of the case in the source, counted from 0. It is stable only while nobody inserts, removes or reorders a case, and the database would silently reinterpret every stored number the day someone does.
    Follow-ups

    From the lesson Enums, sealed traits and ADTs

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  8. Mid to senior

    You model an order's events: placed, paid and shipped, plus three kinds of failure that share a retry rule, some carrying fields of their own. A Java service reads the events too. Would you use an enum or a sealed trait hierarchy, and how would you defend the choice in a design review?

    What it tests
    What enum cases can and cannot hold, grouping cases under a sealed trait, exhaustivity across a hierarchy, and what each encoding looks like from Java.
    First step
    List what the model needs: cases with different fields, a group of failures with a shared supertype and member, and checked matches. Enum cases cannot have bodies or form groups, so the failures point to a sealed hierarchy; then check what the Java service needs.
    Follow-ups

    From the lesson Enums, sealed traits and ADTs

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  9. Fresher to senior

    A nightly job reads a partner's CSV file with val Array(user, amount) = line.split(","). It ran for months, then stopped with scala.MatchError on a line with a note in a third column, and no line after it was processed. Why did the compiler not warn, how do you fix the job, and how do you find similar code?

    What it tests
    Refutable patterns in val definitions, why an Array pattern escapes the warning, matching with a case per shape, error values instead of exceptions for bad input, and finding the pattern in a code base.
    First step
    Name the mechanism: a pattern in a val is a match with one case, so any line that does not have exactly two fields throws MatchError. The compiler warns only when the pattern's type is narrower than the value's, as for first :: rest; Array(user, amount) has the array's own type, so it drew no warning and nothing told the authors the line could fail.
    Follow-ups

    From the lesson Scala 3 pattern matching in depth

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  10. Mid to senior

    A consumer receives messages typed Any and handles batches with case xs: List[Payment] => total(xs). Now and then a ClassCastException is thrown inside total, far from the match, and only for some messages. Explain why the match let the batch through, and how you would make the handling safe.

    What it tests
    Type erasure and unchecked type tests, reading warning E092, testing elements instead of type arguments, ClassTag or TypeTest, and decoding messages into a typed model at the boundary.
    First step
    Explain what the test can check while the program runs: only that the value is a List, because the element type is erased. A batch of other objects passes the case, and the cast fails later, when total reads an element as a Payment. The compiler said so with E092.
    Follow-ups

    From the lesson Scala 3 pattern matching in depth

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  11. Fresher to senior

    A billing service keeps amounts as Long, some in paise and some in rupees, and a refund was paid out 100 times too large. How would you make this mix-up impossible to compile? Compare a case class wrapper, a value class and an opaque type, and say what each costs at run time.

    What it tests
    Using the type system to separate units, the run-time cost of three kinds of wrapper on the JVM, smart constructors, and converting at the edges of the system.
    First step
    Name the root cause: two units share one type, so the compiler cannot tell them apart. Give each unit a type of its own, built only through a factory, with conversions written once, and then choose the wrapper by what it costs where the amounts are stored and passed.
    Follow-ups

    From the lesson Opaque types and value classes

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  12. Mid to senior

    An object had formatPaise(p: Long) and formatGrams(g: Long), which a Java module calls. A teammate made Paise and Grams opaque types over Long and renamed both methods to format, one taking a Paise and one a Grams. The build now fails with E120. Explain the failure, fix it, and say what the Java callers see.

    What it tests
    Erasure of opaque types to their underlying type, how overloads become JVM methods, @targetName and the JVM names it sets, and keeping Java callers working through a refactoring.
    First step
    Start from erasure: the type checker sees format(Paise) and format(Grams), but on the JVM both parameters are long, so both methods would be format(long), and one class cannot hold two methods with the same signature.
    Follow-ups

    From the lesson Opaque types and value classes

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes

All Scala 3 interview questions · The Scala 3 track

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.