forked from alexeygritsenko/Scala-Lections
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlec09.scala
128 lines (106 loc) · 3.75 KB
/
lec09.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
trait Doubled extends IntQueue
{
abstract override def put(x:Int) = {
// В случае трейтов
// super приобретает динамическую характеристику
// и мы не знаем к чему обращаемся
super.put(2*x)
}
}
trait Filtered extends IntQueue
{
abstract override def put(x:Int) = {
if(x > 0) super.put(x)
}
}
trait Incremented extends IntQueue
{
abstract override def put(x:Int) = {
super.put(x + 1)
}
}
// В данном случае трейт "перекроет" метод
// и вызовется put для Doubled, а потом для IntQueue (?)
// (трейт примешивается)
class Q1 extends IntQueue
with Doubled
{
val q1 = new Q1
q1.put(2)
}
// Вызовется Doubled, потом Incremented и IntQueue
class Q1 extends IntQueue
with Incremented
with Doubled
{
val q1 = new Q1
q1.put(3)
}
// Таким образом можно комбинировать, например с Filtered попадет в очередь все что больше нуля
// Можно примешивать к new
val q = new IntQueue with ... // при этом новый класс не создается.
// В случа ниже передать в foo просто очередь нельзя
// (должен быть примешан Filtered)
def foo(q:IntQueue with Filtered)
// case-классы
// Все параметры конструктора неявно считаются val
// У класса реализованы методы сравнения
// Для класса реализован метод toString
// Реализован метод copy
// Автоматически создается объект-компаньон
case class Point(x:Double, y:Double) {
// Как правило тело никто не пишет.
// Они используются для описания каких-то структур.
}
// Создает копию объекта
p.copy(y = 3.2)
// Автоматически создается объект-компаньон
val p = Point(3, 4)
// case класс можно использовать как образец конструктор.
trait Expression
case class Const(value:Double)
case class Plus(left:Expression, right:Expression)
case class Minus(left:Expression, right:Expression)
// Знак минус перед выражением
case class UnaryMinus(exp:Expression)
// def calc
anyexpr match {
case Const(x) => x
case Plus(l,r) => calc(l)+calc(r)
case Minus(l,r) => calc(l)+calc(r)
}
def simple(e:Expression):Expression = {
e match {
case Plus(l, Const(0)) => simple(l) // Упростить упрощенное
case Plus(Const(0), r)) => r
case UnaryMinus(UnaryMinus(x)) => x // x == Expression
// ...
case x => x
}
}
// Экстракторы
// Если хочется свой паттерн написать.
object Twice
{
// Экстрактор
def unapply(s:String):Option[String] // приходит из str в match
{
val lenn = s.length/2
val half = s.substring(0, len)
if(half == s.substring(len))
Some(half) // уезжать в x
// Если вернет None, то шаблон не сопоставится.
else None
}
}
val str = "abab"
str match {
case Twice(x /* Должно попасть ab из str (попадает из half) */) => ...
}
// Сложности!
object IsInt {
def unapply(s:String):Option[Int] // Int, не String
}
str match {
case IsInt(x) => // x может быть составной шаблон (напоминание)
}