Полное сопоставление
Проверка полноты компилятором
«Полное сопоставление» — бесплатный урок Scala for Backend Engineering & Functional Programming на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Scala for Backend Engineering & Functional Programming, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Scala for Backend Engineering & Functional Programming содержит 4 уроков всего.
Что такое полное сопоставление
Сопоставление является полным, если оно обрабатывает каждое возможное значение сопоставляемого типа.
Для запечатанного трейта компилятор знает все варианты и может проверить, что сопоставление учитывает их все.
Полное сопоставление
Если вы обработали каждый вариант запечатанного трейта, компилятор не выдаёт предупреждение.
sealed trait Color
case object Red extends Color
case object Green extends Color
case object Blue extends Color
object Main {
def name(c: Color): String = c match {
case Red => "red"
case Green => "green"
case Blue => "blue"
}
def main(args: Array[String]): Unit = {
println(name(Blue))
}
}Компилятор вас подстрахует
Если вы пропустите вариант, компилятор во время компиляции выдаст предупреждение о неполном сопоставлении.
Это защитный механизм: вы узнаете о пропуске ещё до запуска программы.
Добавление варианта позже
Настоящая польза проявляется при добавлении нового варианта. Каждое неполное сопоставление в кодовой базе выдаст предупреждение и напомнит обработать новый случай.
Это делает рефакторинг безопасным и предсказуемым.
Почему следует избегать шаблона «любой вариант»
Добавление case _ => подавляет предупреждения о неполноте. При последующем добавлении вариантов это может скрыть ошибки.
Для запечатанных ADT лучше явно перечислять каждый вариант, чтобы компилятор продолжал вас защищать.
sealed trait Status
case object Active extends Status
case object Inactive extends Status
object Main {
def label(s: Status): String = s match {
case Active => "on"
case Inactive => "off"
}
def main(args: Array[String]): Unit = {
println(label(Active))
}
}Полнота при наличии данных
Проверка полноты распространяется и на варианты, содержащие данные. Вы связываете поля, но всё равно должны учесть каждый вариант.
sealed trait Shape
case class Circle(r: Double) extends Shape
case class Square(s: Double) extends Shape
object Main {
def area(sh: Shape): Double = sh match {
case Circle(r) => 3.14159 * r * r
case Square(s) => s * s
}
def main(args: Array[String]): Unit = {
println(area(Circle(2)))
println(area(Square(3)))
}
}Сочетание с условиями-ограничителями
Будьте осторожны: условия-ограничители могут сделать сопоставление неполным, потому что компилятор не может доказать, что они охватывают все значения.
Добавьте для того же варианта последний случай без условия, чтобы сохранить полноту.
sealed trait Temp
case class Celsius(v: Int) extends Temp
object Main {
def feel(t: Temp): String = t match {
case Celsius(v) if v >= 30 => "hot"
case Celsius(v) => "not hot"
}
def main(args: Array[String]): Unit = {
println(feel(Celsius(35)))
println(feel(Celsius(10)))
}
}Полнота при работе с Option
Option из стандартной библиотеки — это запечатанный ADT с Some и None. Сопоставление с обоими вариантами является полным.
object Main {
def show(o: Option[Int]): String = o match {
case Some(v) => s"value $v"
case None => "nothing"
}
def main(args: Array[String]): Unit = {
println(show(Some(7)))
println(show(None))
}
}Полнота вложенных сопоставлений
Проверка полноты помогает и при работе с вложенными ADT. Компилятор анализирует каждый уровень, который вы разбираете.
sealed trait Tree
case object Leaf extends Tree
case class Node(v: Int, l: Tree, r: Tree) extends Tree
object Main {
def depth(t: Tree): Int = t match {
case Leaf => 0
case Node(_, l, r) => 1 + math.max(depth(l), depth(r))
}
def main(args: Array[String]): Unit = {
println(depth(Node(1, Leaf, Node(2, Leaf, Leaf))))
}
}Почему это важно
Проверка полноты компилятором даёт вам:
- Уверенность, что обработан каждый случай
- Автоматические напоминания при расширении ADT
- Меньше ошибок MatchErrors во время выполнения
- Более безопасный масштабный рефакторинг
Объединяем всё вместе
Запечатанный ADT с полным покрытием вариантов. Добавление нового варианта вызвало бы здесь предупреждение компилятора.
sealed trait Command
case object Start extends Command
case object Stop extends Command
case class SetSpeed(v: Int) extends Command
object Main {
def run(c: Command): String = c match {
case Start => "starting"
case Stop => "stopping"
case SetSpeed(v) => s"speed $v"
}
def main(args: Array[String]): Unit = {
List(Start, SetSpeed(5), Stop).foreach(c => println(run(c)))
}
}Быстрая проверка
Проверьте, насколько хорошо вы поняли полное сопоставление.
Итоги
Вы узнали о полном сопоставлении:
- Сопоставление является полным, если охватывает каждый вариант
- Для запечатанных трейтов компилятор проверяет это и предупреждает о пропусках
- Добавление варианта выявляет все неполные сопоставления
- Избегайте
case _в запечатанных ADT, чтобы сохранить эту защиту - Условия-ограничители могут нарушить полноту; добавляйте вариант без условия
Изучай Scala с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 39
- Уроки
- 143
Часто задаваемые вопросы
Урок «Полное сопоставление» бесплатный?
Да — полный текст урока «Полное сопоставление» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Scala for Backend Engineering & Functional Programming, подпишись на CoddyKit PRO. Курс Scala for Backend Engineering & Functional Programming содержит 4 уроков всего.
Чему я научусь в уроке «Полное сопоставление»?
Проверка полноты компилятором Ты практикуешь Scala for Backend Engineering & Functional Programming с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Scala for Backend Engineering & Functional Programming?
Предыдущий опыт не требуется. Scala for Backend Engineering & Functional Programming на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Полное сопоставление»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Scala for Backend Engineering & Functional Programming?
Да. Каждый урок Scala for Backend Engineering & Functional Programming включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Классы case
- Запечатанные трейты
- Алгебраические типы данных
- Полное сопоставление