88.47K
Category: programmingprogramming

Сопоставление с образцом: Переключатели. Определители типа. Шаблоны с переменными. Сase-классы

1.

Сопоставление с образцом
• Переключатели
• Определители типа
• Шаблоны с переменными
• Сase-классы
Сопоставление с образцом какого-либо
объекта осуществляется с помощью оператора
match, значение которого всегда вычисляется и
имеет определенный тип, часто не связанный с
типом анализируемого объекта.

2.

Переключатели
var cChar: Char = '4'
cСhar match {
case '+' => s = 1
case _ if ('0' to '9') contains cChar
=> s = -1
case _
=> s = 0
}
Здесь использован ограничитель шаблона, который
располагается после шаблона и начинается с if.
Универсальный шаблон сопоставления _
соответствует любому значению.

3.

Определение типа
var example:Any="abcdef"
example match {
case x: Int => println("int: " + x)
case y: String if y.length >5 =>
println("longString")
case y: String if y.length <=5 =>
println("shortString")
case z:Double => println("double" + z)
case _ => println("unknown")
}

4.

Шаблоны с переменными
var cList = List(5,9,12)
cList match {
case 4::t => println(t)
case y::z => println(z)
case _ => println(cList
}
В шаблоне могут присутствовать переменные и
константы. В данном случае переменным z и t могут
соответствовать любые списки, а y – только значение типа
Int.
y, z, t - локальные переменные, которые могут
использоваться только внутри оператора match. Классы, к
которым относятся локальные переменные, определяются
по контексту.

5.

Класс Option
var sOpt:Option[Int]=Some(5)
sOpt match {
case None => println ("no value")
case Some(s) => println (s)
}
println(sOpt.get)
Класс Option используется, если переменная, относящаяся к
какому-то классу, может и не принимать никакого значения.
Тогда считается, что значение равно None.
В Java примерным аналогом является Optional.
Для sOpt возможными значениями будут Some(-2), Some(0),
Some(121) и т.д. Класс Option - это по сути контейнер для
элементов заданного типа.
Например, когда мы обращаемся к методу get при работе с
отображением Map, результат выдается в форме Option.
Для извлечения значения из контейнера поможет метод get.

6.

Класс Option
val aM=Map('d'-> 12, 'g'->4, 's'->55)
println(aM.get('d'))
println(aM.get('d').get)
Когда мы обращаемся к методу get при работе с
отображением Map, результат выдается в форме Option.
Для извлечения значения из контейнера поможет, в свою
очередь, метод get.

7.

Класс Option
class Employee
var sOpt: Option[Employee]=Some(new Employee)
sOpt match {
case None => println("no value")
case Some(s1) => println(s1.getClass)
}

8.

Case-классы
abstract class User
case class RegUser(val name: String) extends User
case class AnonymUser() extends User
val users = List(RegUser("Oleg"), AnonymUser(),
RegUser("Vlad"))
def register(user: User): Unit = user match {
case RegUser(name_2) => println("User " + name_2 + "
registered")
case AnonymUser()
=> println("Anonymous user can't
be registered")
}
users.foreach(register)

9.

Case-классы
По умолчанию для case-класса создается объекткомпаньон с методами apply и unapply. Последний
служит для выделения из объекта case-класса
значений его полей. Для создания объекта caseкласса оператор new не обязателен.
Case-классы
получают
автоматически
сгенерированные методы equals и hashCode, а не просто
наследуют их от базового класса Any. Для caseклассов проверяется равенство значений, а не
равенство адресов (для обычных классов, потомков
AnyRef, равенство адресов). В остальном case-классы
не отличаются от обычных классов.
Для потомков AnyVal и коллекций также
проверяется равенство значений.

10.

Case-классы
case class Person(name: String, age: Int)
class Employee
case class Engineer(id: Person)extends Employee
case class Manager(id: Person, subordinates: List[Employee])
extends Employee
val us = List(Engineer(Person("Max",24)),Engineer(Person("Mark", 55)),
Manager(Person("Ivan",40), List(new Employee)),
Manager(Person("Vlad",30), List(new Employee,new Employee)))
def isMaxim(p: Employee):Unit = p match {
case Engineer(Person("Max", _)) => println(true)
case Manager(Person("Max", _), _) => println(true)
case _ => println(false) }
def isManagerOver40(p: Employee):Unit = p match {
case Manager(Person(_, age), _) if age > 40 => println(true)
case _ => println(false) }
def numOfsub(employee: Employee): Unit =
employee match {
case Manager(_,subordinates) => println(subordinates.length)
case _ => println("0")}
us.foreach(numOfsub)
Person должен быть case-классом, поскольку он использован в шаблоне и требует метода
unapply для выделения полей.

11.

Задания
• Cформировать список из произвольного списка,
удалив первый и последний элементы. Применить
оператор сопоставления с образцом match.
• Используя оператор сопоставления с образцом match,
определить сумму элементов List[Int].

12.

Управляющие структуры
• Выражение if
• Циклы while
• Выражение for

13.

Выражение if
Значение выражения if вычисляется.
Поскольку зарезервированное слово then
может не использоваться, логическое
выражение после if заключается в скобки.
def main(args: Array[String]) = {
println( if (!args.isEmpty)
args(0) else "no")
}

14.

Выражение if
Если предусматривается выполнение
каких-то действий, а не вычисление
значения, то типом результата будет Unit и
if можно использовать как оператор
if (true) println("yes")

15.

Циклы while c пред- и постусловием
while (<предусловие>) {
<тело цикла>
}
do {
<тело цикла>
} while (<постусловие>)
Типом результата всегда является Unit. В
функциональные языки циклы while обычно не
включают.

16.

Реализация While в виде
функции
def While(p: => Boolean)(s: => Unit) {
if (p) {
s; While(p)(s)
}
}

17.

Выражение for
Использование выражения for позволяет решать
множество задач.
1. Обход всех элементов коллекций
for (a<- bCol) {....}
2. Использование типа Range
for (a<- 0 to 9) {....}
Выражение, стоящее после for называется
генератором.
3. Реализация вложенных циклов с помощью
одного for
Для этого нужны несколько генераторов.

18.

Выражение for
В выражениях for можно использовать фильтры
в виде выражений if. Тогда будут рассматриваться
не все элементы коллекции, а только те, которые
проходят фильтр.
def main(args: Array[String]) = {
for (v<-args if v contains "0")
println(v)
}

19.

Выражение for
Инструкция yield
val s= for (i <- 0 to 2; j <- "abcd")
yield (i + j.toInt)
Когда тело цикла начинается с инструкции
yield, будет сгенерирована коллекция путем
добавления в нее по одному элементу на каждой
итерации.
В данном случае Vector.
English     Русский Rules