3μ£Όμ°¨ (11 ~ 15 Chapter)
Chapter 11 μ€μΉΌλΌμ κ³μΈ΅κ΅¬μ‘°
λͺ¨λ ν΄λμ€κ° Any
μ μλΈν΄λμ€μ΄κΈ° λλ¬Έμ, Any
κ° μ μν΄λ λ©μλλ λͺ¨λ '보νΈμ μΈ' λ©μλλ€.
11.1 μ€μΉΌλΌμ ν΄λμ€ κ³μΈ΅κ΅¬μ‘°
κ³μΈ΅μ μ΅μμμλ Any
ν΄λμ€κ° μλ€.
λ£¨νΈ (root) ν΄λμ€ Any
μλ μλΈν΄λμ€κ° λ μλλ°, λ°λ‘ AnyVal
κ³Ό AnyRef
λ€.
- AnyVal : λͺ¨λ μ€μΉΌλΌκ° ν΄λμ€ (value class) μ λΆλͺ¨ ν΄λμ€
- AnyRef : λͺ¨λ μ€μΉΌλΌμ μ°Έμ‘° ν΄λμ€ (reference class) μ κΈ°λ° ν΄λμ€
μ€μΉΌλΌκ° κΈ°λ³Έμ μΌλ‘ μ 곡νλ κ° ν΄λμ€λ λ€μκ³Ό κ°λ€.
Byte
,Short
,Char
,Int
,Long
,Float
,Double
,Boolean
,Unit
μλ₯Ό λ€λ©΄ 42
λ Int
μ μΈμ€ν΄μ€μ΄κ³ , 'x'
λ Char
μ μΈμ€ν΄μ€μ΄κ³ , false
λ Boolean
μ μΈμ€ν΄μ€μ΄λ€.
μ΄ κ° ν΄λμ€λ new
λ₯Ό μ¬μ©νμ¬ μΈμ€ν΄μ€ν ν μ μλ€. λͺ¨λ κ° ν΄λμ€λ₯Ό μΆμ ν΄λμ€μΈ λμμ νμ΄λ ν΄λμ€ (final class) λ‘ λ§λλ κΈ°λ²μ μ¬μ©νμ¬ μ μ½μ κ°νλ€.
11.2 μ¬λ¬ κΈ°λ³Έ ν΄λμ€λ₯Ό μ΄λ»κ² ꡬννλκ°?
boolean isEqual(Integer x, Integer y) {
return x == y;
}
System.out.println(isEqual(421, 421));
μ μλ° μ½λλ λνΌ (wrapper) ν΄λμ€μ λμ λ κ°μ λΉκ΅ μ°μ°μ (==, !=) λ₯Ό ν΅νμ¬ λΉκ΅κ° λΆκ°λ₯νλ€.
Integer
κ° μ°Έμ‘° νμ
μ΄ μλκΈ° λλ¬Έμ μΈλ°μ±νμ¬ κ°μ λΉκ΅ν΄μΌ νλ€.
scala> def isEqual(x: Int, y: Int) = x == y
isEqual: (x: Int, y:Int)Boolean
scala> isEqual(421, 421)
res10: Boolean = true
scala> def isEqual(x: Any, y: Any) = x == y
isEqual: (x: Any, y:Any)Boolean
scala> isEqual(421, 421)
res11: Boolean = true
μ€μΉΌλΌλ μλ° μ½λμλ λ€λ₯΄κ² λ§λ ν κ·ΈλμΌ νλ λ°©μλλ‘ λμλλ€.
νμ§λ§ μ¬μ©μκ° μ μν λμΌμ± λμ μ°Έμ‘° λμΌμ±μ΄ νμν κ²½μ°λ μλ€.
μ΄λ¬ν κ²½μ°μλ ν΄μ μ½μ¦ (hash cons) λ₯Ό μ¬μ©νκ³ μΆμ κ²½μ°κ° μλ€. μ°Έμ‘° λμΌμ±μ μ¬μ©νκ² λ§λ€μ΄λ eq
λΌλ λ©μλκ° μλ€.
scala> val x = new String("abc")
x: String = abc
scala> val y = new String("abc")
y: String = abc
scala> x == y
res13: Boolean = true
scala> x eq y
res13: Boolean = false
scala> x ne y
res13: Boolean = true
μ€μΉΌλΌμ λμΌμ±μ λν΄μ 30μ₯μμ μμΈν λ€λ£°κ²μ΄λ€.
11.3 λ°λ₯μ μλ νμ
Nothing
νμ
μ μ€μΉΌλΌ ν΄λμ€ κ³μΈ΅μ 맨 λ°λ°λ₯μ μ‘΄μ¬νλ€.
Nothing
μ λΉμ μμ μ’
λ£λ₯Ό νμνλκ²μ΄λ€.
Nothing
μ λͺ¨λ νμ
μ μλΈνμ
μ΄κΈ° λλ¬Έμ, error
μ κ°μ λ©μλλ₯Ό λ€μν κ³³μμ μ μ°νκ² μ¬μ©κ°λ₯νλ€.
def divide(x: Int, y: Int): Int =
if (y != 0) x / y
else sys.error("can't divide by zero")
μ μ½λμμ λ°ν νμ
μ΄ Int
μ΄μ§λ§ Nothing
μ λͺ¨λ νμ
μ μλΈνμ
μ΄κΈ° λλ¬Έμ λ©μλμ λ°ννμ
μμ μꡬνλ λλ‘ Int
κ° λ μ μλ€.
11.4 μμ λ§μ κ° ν΄λμ€ μ μ
κ° ν΄λμ€λ₯Ό μ μνκ³ μΆμΌλ©΄ AnyVal
μ μλΈν΄λμ€λ‘ λ§λ€λ©΄ λλ€.
class Dollars(val amount: Int) extends AnyVal {
override def toString() = "$" + amount
}
ν κ°μ§ νμ λ§ λ¨μ©νλ κ²μ λ§κΈ°
μ€μΉΌλΌ ν΄λμ€ κ³μΈ΅μ κ°μ₯ μ νμ©νκ³ μΆλ€λ©΄, λ¬Έμ μμμ μ λ€μ΄λ§λ μλ‘μ΄ ν΄λμ€λ₯Ό μ μνλΌ.
class Anchor(val value: String) extends AnyVal
class Style(val value: String) extends AnyVal
class Text(val value: String) extends AnyVal
class Html(val value: String) extends AnyVal
μ κ°μ ν΄λμ€κ° μλ€λ©΄ μ’ λ μμΈν νμ μκ·Έλμ²λ₯Ό κ°λ title ν¨μλ₯Ό λ§λ€ μ μλ€.
def title(title: Text, anchor: Anchor, style: Style): Html =
new Html(
s"<a id='${anchor.value}'>" +
s"<h1 class='${style.value}'>" +
text.value +
"</h1></a>"
)
11.5 κ²°λ‘
λ€μ μ₯μμ λ―Ήμ€μΈ (mix in) ν©μ±μ μ΄ν΄ν μ€λΉκ° λμλ€.
Chapter 12 νΈλ μ΄νΈ
μ€μΉΌλΌμμ νΈλ μ΄νΈλ μ½λ μ¬μ¬μ©μ κ·Όκ°μ μ΄λ£¨λ λ¨μλ€.
νλμ μνΌν΄λμ€λ§ κ°λ ν΄λμ€μ μμκ³Όλ λ¬λ¦¬, νΈλ μ΄νΈμ κ²½μ° λͺκ°λΌλ νΌν©ν΄ μ¬μ©ν μ μλ€.
12.1 νΈλ μ΄νΈμ λμ μ리
νΈλ μ΄νΈλ₯Ό μ μνκ³ λλ©΄ extends
λ with
ν€μλλ₯Ό μ¬μ©ν΄ ν΄λμ€μ μ‘°ν©νμ¬ μ¬μ©ν μ μλ€.
μ€μΉΌλΌ νλ‘κ·Έλλ¨Έλ νΈλ μ΄νΈλ₯Ό μ¬μ©ν λ μμ보λ€λ λ―Ήμ€μΈ (mix in) μ μ¬μ©νλ €νλ€.
class Frog extends Philosophical {
override def to String = "green"
}
νΈλ μ΄νΈλ₯Ό λ―Ήμ€μΈν λλ extends
ν€μλλ₯Ό μ¬μ©νλ€.
extends
ν€μλλ₯Ό μ¬μ©νλ©΄ νΈλ μ΄νΈμ μνΌν΄λμ€λ₯Ό μμμ μΌλ‘ μμνλ€.
μ¬λ¬ νΈλ μ΄νΈλ₯Ό λ―Ήμ€μΈ νλ €λ©΄ with
ꡬ문μ μΆκ°νλ©΄ λλ€.
class Frog extends Animal with Philosophical {
override def toString = "green"
}
class Frog extends Animal with Philosophical with HasLegs {
override def toString = "green"
}
ν΄λμ€μ νΈλ μ΄νΈμ μ°¨μ΄μ μ λ€μκ³Ό κ°λ€.
- νΈλ μ΄νΈλ ν΄λμ€ νλΌλ―Έν° (ν΄λμ€μ μ£Ό μμ±μμ μ λ¬ν νλΌλ―Έν°) λ₯Ό κ°μ§ μ μλ€.
- ν΄λμ€μμλ
super
νΈμΆμ μ μ μΌλ‘ λ°μΈλ©νμ§λ§, νΈλ μ΄νΈμμλ λμ μΌλ‘ λ°μΈλ©νλ€λ μ μ΄λ€.
12.2 κ°κ²°ν μΈν°νμ΄μ€μ νλΆν μΈν°νμ΄μ€
νΈλ μ΄νΈμ μ£Όλ μ¬μ©λ°©λ²μ μ΄λ€ ν΄λμ€μ κ·Έ ν΄λμ€κ° μ΄λ―Έ κ°κ³ μλ λ©μλλ₯Ό κΈ°λ°μΌλ‘ νλ μλ‘μ΄ λ©μλλ₯Ό μΆκ°νλ λ²μ΄λ€.
κ°κ²°ν μΈν°νμ΄μ€ (thin interface) λ₯Ό νλΆν μΈν°νμ΄μ€ (rich interface) λ‘ λ§λ€ λ νΈλ μ΄νΈλ₯Ό μ¬μ©ν μ μλ€.
ꡬ체μ μΈ λ©μλ ꡬνμ νΈλ μ΄νΈμ λν μ μμΌλ©΄ νλΆν μΈν°νμ΄μ€ μͺ½μ λΉμ©λλΉ ν¨μ©μ΄ λ μ’μμ§λ€.
12.3 μμ : μ§μ¬κ°ν κ°μ²΄
νλΆν νΈλ μ΄νΈλ₯Ό μ¬μ©ν΄ μ½λμ λ°λ³΅μ νΌν μ μλ€.
trait Rectangular {
def topLeft: Point
def bottomRight: Point
def left = topLeft.x
def right = bottomRight.x
def width = right - left
// μ¬λ¬ κΈ°ν κ΄λ ¨ λ©μλ...
}
12.4 Ordered νΈλ μ΄νΈ
μ€μΉΌλΌμμ μ 곡νλ Ordered
λΌλ νΈλ μ΄νΈλ₯Ό μ¬μ©ν κ²½μ° νλμ λΉκ΅ μ°μ°μλ§ μμ±νλ©΄ λͺ¨λ λΉκ΅ μ°μ°μ ꡬνμ λμ ν μ μλ€.
Ordered
νΈλ μ΄νΈκ° κ·Έ νλμ λ©μλ ꡬνμ κΈ°λ°μΌλ‘ <
, >
, <=
, =>
λ₯Ό μ 곡νλ€.
compare
λ©μλλ§ κ΅¬ννλ©΄ Ordered
νΈλ μ΄νΈκ° λΉκ΅ λ©μλλ₯Ό μ κ³΅ν΄ ν΄λμ€λ₯Ό νλΆνκ² ν΄μ€λ€.
Ordered
νΈλ μ΄νΈκ° equals
λ₯Ό μ μνμ§ μλλ€. μ΄λ λΉκ΅κ΄μ μμ equals
λ₯Ό ꡬννλ €λ©΄ μ λ¬ λ°μ κ°μ²΄μ νμ
μ μμμΌ νλ€.
νμ§λ§ νμ
μκ±° (type erasure) λλ¬Έμ Ordered
νΈλ μ΄νΈλ μ΄λ¬ν κ²μ¬λ₯Ό μνν μ μλ€.
12.5 νΈλ μ΄νΈλ₯Ό μ΄μ©ν΄ λ³κ²½ μμ μ¬λ¦¬κΈ°
ν΄λμ€μ μμ μ μλ λ³κ²½μ μ μ©ν΄λ³΄μ.
abstract class IntQueue {
def get(): Int
def put(x: Int): Unit
}
import scala.collection.mutable.ArrayBuffer
class BasicIntQueue extends IntQueue {
private val bu = new ArrayBuffer[int]
def get() = buf.remove(0)
def put(x: Int) = { buf += x }
}
μμμ μλ λ³κ²½μ λνλ΄λ Doubling
νΈλ μ΄νΈ
trait Doubling extends IntQueue {
abstract override def put(x: Int) = { super.put(2 * x) }
}
μ΄ μ μΈμ Doubling
νΈλ μ΄νΈκ° IntQueue
λ₯Ό μμν ν΄λμ€μλ§ λ―Ήμ€μΈ λ μ μλ€λ μ μ΄λ€.
λ―Ήμ€μΈμ μμκ° μ€μνλ°, λ―Ήμ€μΈν ν΄λμ€μ λ©μλλ₯Ό νΈμΆνλ©΄ κ°μ₯ μ€λ₯Έμͺ½μ μλ νΈλ μ΄νΈμ λ©μλλ₯Ό λ¨Όμ νΈμΆνλ€.
12.6 μ λ€μ€μμμ μλλκ° ?
νΈλ μ΄νΈλ₯Ό μ¬μ©ν λμλ νΉμ ν΄λμ€μ λ―Ήμ€μΈν ν΄λμ€μ νΈλ μ΄νΈλ₯Ό μ νν (linearization) ν΄μ μ΄λ€ λ©μλλ₯Ό νΈμΆν μ§ κ²°μ νλ€.
λͺ¨λ μ ννμμ μ΄λ€ ν΄λμ€λ μμ μ μνΌν΄λμ€λ λ―Ήμ€μΈν΄ λ£μ νΈλ μ΄νΈλ³΄λ€ μμ μμΉ νλ€λ μ μ΄λ€.
μλμ κ°μ΄ μ¬λ¬ νΈλ μ΄νΈλ₯Ό λ―Ήμ€μΈ ν Cat
ν΄λμ€κ° μλ€κ³ κ°μ νμ.
class Animal
trait Furry extends Animal
trait HasLegs extends Animal
trait FourLegged extends Animal
class Cat extends Animal with Furry with FourLegged
Cat
ν΄λμ€ μ ννμ λ§μ§λ§ λΆλΆμ Cat
μ μνΌν΄λμ€μΈ Animal
μ μ ννν κ²°κ³Όμ΄λ€.
12.7 νΈλ μ΄νΈλ μλλ, μ΄κ²μ΄ λ¬Έμ λ‘λ€.
νκ³ ν κ·μΉμ μμ§λ§ λͺκ°μ§ κ°μ΄λλΌμΈμ μ μνλ©΄ λ€μκ³Ό κ°λ€.
- ν΄λμ€λ₯Ό μ¬μ©ν λ
- μ΄λ€ νμλ₯Ό μ¬μ¬μ©νμ§ μμκ±°λΌλ©΄
- νΈλ μ΄νΈλ₯Ό μ¬μ©ν λ
- μλ‘ κ΄λ ¨μ΄ μλ ν΄λμ€μμ μ΄λ€ νμλ₯Ό μ¬λ¬ λ² μ¬μ¬μ©ν΄μΌ νλ€λ©΄
- μΆμν΄λμ€λ₯Ό μ¬μ©ν λ
- μ€μΉΌλΌμμ μ μν λ΄μ©μ μλ° μ½λμμ μμν΄μΌ νλ€λ©΄
12.8 κ²°λ‘
νΈλ μ΄νΈλ μμμ ν΅ν΄ μ¬μ¬μ©ν μ μλ κΈ°λ³Έ μ½λ λ¨μλ€.
Chapter 13 ν¨ν€μ§μ μν¬νΈ
κ·λͺ¨κ° ν° νλ‘κ·Έλ¨μ μμ±ν λλ νλ‘κ·Έλ¨μ μ¬λ¬ λΆλΆμ΄ μλ‘ μμ‘΄νλ μ λλ₯Ό λνλ΄λ 컀νλ§ (coupling) μ μ΅μννλ κ²μ΄ μ€μνλ€.
13.1 ν¨ν€μ§ μμ μ½λ μμ±νκΈ°
μ§κΈκΉμ§ λ΄€λ μ½λ μμ λ€μ μ΄λ¦ μλ ν¨ν€μ§ μμμ μμ±νμλ€.
package
μ λ€μμ μ€κ΄νΈκ° μμΌλ©΄, κ·Έ μ€κ΄νΈ μμ μλ μ μλ λͺ¨λ ꡬ ν¨ν€μ§μ μνλ€.
μ΄λ° λ¬Έλ²μ ν¨ν€μ§ (packaging) μ΄λΌ λΆλ₯Έλ€.
package bobsrockets.navigation {
class Navigator
}
μμ μ¬λ¬ ν¨ν€μ§λ₯Ό λ£μ λλ μλμ κ°μ΄ μ¬μ©νλ€.
package bobsrockets {
package navigation {
class Naviator
package tests {
class NavigaorSuite
}
}
}
13.2 κ΄λ ¨ μ½λμ κ°κ²°νκ² μ κ·ΌνκΈ°
μ½λλ₯Ό ν¨ν€μ§ κ³μΈ΅μ¬ λλλ μ΄μ λ μ¬λλ€μ΄ μ½λλ₯Ό νμ΄λ³Ό λ λμμ μ£ΌκΈ° μν λͺ©μ λ μμ§λ§,
μ»΄νμΌλ¬λ κ°μ ν¨ν€μ§ μμ μλ μ½λκ° μλ‘ κ΄λ ¨ μμμ μ μ μλ€.
package bobsrockets {
package navigation {
class Navigator {
// bobsrockets.navigation.StarMap μ μΈ νμκ° μλ€.
val map = new StarMap
}
class StarMap
}
class Ship {
// bobsrockets.navigation.Navigator λ₯Ό μΈ νμκ° μλ€.
val nav = new navigation.Navigator
}
package fleets {
class Fleet {
// bobsrockets.Ship μ μΈ νμκ° μλ€.
def addShip() = { new Ship }
}
}
}
μ μ½λλ λ€μ μΈκ°μ§ κ·μΉμ λ°λ₯Έλ€.
- μ΄λ€ ν΄λμ€κ° μν ν¨ν€μ§ μμμλ μ λμ¬κ° μμ΄λ ν΄λΉ ν΄λμ€μ μ κ·Όν μ μλ€.
- μ΄λ€ ν¨μΊμ§λ₯Ό ν¬ν¨νλ (λΆλͺ¨) ν¨ν€μ§ μμμλ ν΄λΉ ν¨ν€μ§μ μ΄λ€ μ λμ΄λ λΆμ΄μ§ μκ³ μ κ·Όν μ μλ€.
- μ€κ΄νΈ ν¨ν€μ§ λ¬Έλ²μ μ¬μ©νλ©΄ κ·Έ ν¨ν€μ§ μ€μ½ν λ°μμ μ κ·Ό κ°λ₯ν λͺ¨λ μ΄λ¦μ κ·Έ ν¨ν€μ§ μμμλ μΈ μ μλ€.
λν μΆκ°μ μΌλ‘ μ€μΉΌλΌμμ μ 곡νλ _root_
ν¨ν€μ§ λ¬Έλ²μ ν΅ν΄ νμ ν¨ν€μ§μμ λ€λ₯Έ ν¨ν€μ§λ‘ μ κ·Όμ΄ κ°λ₯νλ€.
package launch {
class Booster3
}
package bobsrockets {
package navigation {
package launch {
class Booster1
}
class MissionControl {
val booster1 = new launch.Booster1
val booster2 = new bobsrockets.launch.Booster2
val booster3 = new _root_.launch.Booster3
}
}
}
λͺ¨λ μ΅μμ ν¨ν€μ§λ _root_
ν¨ν€μ§μ λ©€λ²λ‘ μ·¨κΈνλ€.
13.3 μν¬νΈ
package bobsdelights
abstract class Fruit(
val name: String,
val color: String
)
object Fruits {
object Apple extends Fruit("apple", "red")
object Orange extends Fruit("orange", "orange")
orbject Pear extends Fruit("pear", "yellowish")
val menu = List(Apple, Orange, Pear)
}
// Fruit μ μ κ·Ό
import bobsdelights.Fruit
// bobsdelights μ λͺ¨λ λ©€λ²μ μ κ·Ό
import bobsdelights._
// Fruits μ λͺ¨λ λ©€λ²μ μ κ·Ό
import bobsdelights.Fruit._
μν¬νΈ μ λ ν° (import selector) μ¬μ©
// Fruits μ Apple κ³Ό Orange λ§μ λΆλ¬μ¨λ€.
import Fruit.{Apple, Orange}
// Apple μ McIntosh λ‘ μ΄λ¦μ λ°κΎΌλ€.
import Fruit.{Apple => McIntosh, Orange}
// Fruits μ Pear λ₯Ό μ μΈν λͺ¨λ λ©€λ²λ₯Ό λΆλ¬μ¨λ€.
import Fruits.{Pear => _, _}
13.4 μμμ μν¬νΈ
μ€μΉΌλΌλ λͺ¨λ νλ‘κ·Έλ¨μμ λͺκ°μ§ μν¬νΈλ₯Ό νμ κΈ°λ³Έμ μΌλ‘ μΆκ°λλ€.
import java.lang._
import scala._
import Predef._
Predef κ°μ²΄λ νμ , λ©μλ κ·Έλ¦¬κ³ μ€μΉΌλΌμμ μ¬μ©νλ μμμ λ³ν (implicit conversion) μ ν¬ν¨νλ€.
μ€μΉΌλΌμμλ λμ€μ μν¬νΈν ν¨ν€μ§κ° λ μμμ μν¬νΈν κ²μ κ°λ¦°λ€
λλ¬Έμ StringBuilder
λ₯Ό μ¬μ©νλ©΄ java.lang.StringBuilder
κ° μλλΌ scala.StringBuilder
λ₯Ό μμμ μΌλ‘ κ°λ₯΄ν¨λ€.
13.5 μ κ·Ό μμμ
ν¨ν€μ§, ν΄λμ€, κ°μ²΄ λ©€λ² μμ private
, protected
λ±μ μ κ·Ό μμμλ₯Ό λ μ μλ€.
λΉκ³΅κ° λ©€λ² (private)
μ€μ§ κ·Έ μ μλ₯Ό ν¬ν¨ν ν΄λμ€λ κ°μ²΄ λ΄λΆμμλ§ μ κ·Όν μ μλ€.
λ³΄νΈ λ©€λ² (protedted)
μ€μΉΌλΌμμλ λ³΄νΈ λ©€λ²λ₯Ό μ μν ν΄λμ€μ μλΈ ν΄λμμμλ§ κ·Έ λ©€λ²μ μ κ·Ό ν μ μλ€.
κ³΅κ° λ©€λ² (public)
private
λ protected
κ° μλ λ©€λ²λ κ³΅κ° λ©€λ²μ΄λ€.
λ³΄νΈ μ€μ½ν
μ κ·Ό μμμλ₯Ό μ§μ μλ‘ νμ₯ ν μ μλ€.
package bobsrockets
package navigation {
private[bobsrockets] class Navigator {
protected[navigation] def useStarChart() = {}
class LegOfJourney {
private[Navigator] val distance = 100
}
private[this] var speed = 200
}
}
package launch {
import navigation._
object Vehicle {
private[launch] val guide = new Navigator
}
}
κ°μμ±κ³Ό λλ° κ°μ²΄
class Rocket {
import Rocket.fuel
private def canGoHomeAgain = fuel > 20
}
object Rocket {
private def fuel = 10
def chooseStrategy(rocket: Rocket) = {
if (rocket.canGoHomeAgain)
goHome()
else
pickAStar()
}
def goHome() = {}
def pickAStar() = {}
}
Rocket
ν΄λμ€λ Rocket
κ°μ²΄μ fuel
λΉκ³΅κ° λ©μλμ μ κ·Όν μ μλ€.
13.6 ν¨ν€μ§ κ°μ²΄
μ€μΉΌλΌμμλ ν¨ν€μ§ μ 체μ λμ°λ―Έ λ©μλ (helper method) λ₯Ό λκ³ μΆλ€λ©΄, ν¨ν€μ§μ μ΅μμ μμ€μ λ£μΌλ©΄ λλ€.
package object bobsdelights {
def showFruit(fruit: Fruit) = {
import fruit._
println(name + "s are " + color)
}
}
package printmneu
import bobsdelights.Fruits
import bobsdelights.showFruit
object PrintMenu {
def main(args: Array[String]) = {
for (fruit <- Fruits.menu) {
showFruit(fruit)
}
}
}
ν¨ν€μ§ κ°μ²΄λ₯Ό μ¬μ©νλ λ€λ₯Έ μ©λλ νμ λ³λͺ (type alias) μ μμμ λ³ν (implicit conversion) μ λ£κΈ° μν΄ μ¬μ©νλ κ²½μ°κ° λ§λ€.
13.7 κ²°λ‘
ν¨ν€μ§λ₯Ό μ¬μ©νλ©΄ μ½κ³ μΈλͺ¨ μκ² λͺ¨λνκ° κ°λ₯νλ€.
Chapter 14 λ¨μΈλ¬Έκ³Ό ν μ€νΈ
μ΄ μ₯μμλ μμ±ν μννΈμ¨μ΄κ° μ λλ‘ λμνλμ§ νμΈν μ μλ λκ°μ§ λ°©λ²μ 보μ¬μ€λ€.
14.1 λ¨μΈλ¬Έ
μ€μΉΌλΌμμλ assert
λ©μλλ₯Ό νΈμΆνλ λ°©λ²μΌλ‘ λ¨μΈλ¬Έμ μμ±νλ€.
λ¨μΈλ¬Έμ μ‘°κ±΄μ΄ μΆ©μ‘±λμ§ μλ κ²½μ°μλ AssertionError
λ₯Ό λ°μμν¨λ€.
μΈμλ₯Ό 2κ° λ°λ λ¨μΈλ¬Έλ μλλ° assert(쑰건, μ€λͺ
)
μΌλ‘ ꡬμ±λλ€.
μ΄ μ€λͺ
μ λ°μ΄ν° νμ
μ Any
μ΄λ©° μ΄λ€ κ°μ²΄λΌλ λκΈΈμ μλ€.
def above(that: Element): Element = {
val this1 = this widen that.width
val that1 = that widen this.width
assert(this1.width == that1.width)
elem(this1.contents ++ that1.contents)
}
μμ λμΌν κΈ°λ₯μΌλ‘ ensuring
μ μ¬μ©νμ¬ ν¨μμ κ²°κ³Ό νμΈνκΈ°κ° μλ€.
private def widen(w: Int): Element =
if (w <= width)
this
else {
val left = elem(' ', (w - width) / 2, height)
val right = elem(' ', w - width - left.width, height)
left beside this beside right
} ensuring (w <= _.width)
JVM μμ
-ea
λ-da
λͺ λ Ήν μ΅μ μ μ¬μ©νλ©΄assert
μensuring
λμμ μΌκ±°λ λμκ° μλ€.
14.2 μ€μΉΌλΌμμ ν μ€νΈνκΈ°
μ€μΉΌλΌμμλ μ¬λ¬ ν μ€νΈ λκ΅¬κ° μ‘΄μ¬νλ€.
- μ€μΉΌλΌ ν μ€νΈ (Scala Test)
- μ€μΉΌλΌ μ€ν©μ€2 (Scala Spec2)
- μ€μΉΌλΌ μ²΄ν¬ (Scala Check)
μ€μΉΌλΌ ν
μ€νΈλ κ°μ₯ μ μ°ν ν
μ€νΈ νλ μμν¬μ΄λ€.
λ€λ₯Έ λ¬Έμ λ₯Ό νκΈ° μν΄ μ½κ² 컀μ€ν°λ§μ΄μ§ ν μ μλ€.
AnyFunSuite
λ‘ μμ±νλ©° JUnit μ κ²½νν΄λ³Έ κ°λ°μλ μ΅μ ν κ²μ΄λ€.
import org.scalatest.funsuite.AnyFunSuite
import Element.elem
class ElementSuite extends AnyFunSuite {
test("elem result should have passed width") {
val ele = elem('x', 2, 3)
assert(ele.width == 2)
}
}
μ€μΉΌλΌ ν μ€νΈμμ μ€μ¬μ μΈ κ°λ μ ν μ€νΈ μ§ν©μΈ μ€μνΈ (suite) μ΄λ€.
ν
μ€νΈλ μμν΄μ μ±κ³΅ νΉμ μ€ν¨, λκΈ°, μ·¨μ ν μ μλ μ΄λ¦μ΄ μλ μ΄λ€κ²λ€μ΄λ€.
νΈλ μ΄νΈ μ€μνΈ (trait suite) λ ν
μ€νΈλ₯Ό μ€ννκΈ° μν΄ μ¬μ μ μ€λΉλ μλͺ
μ£ΌκΈ° λ©μλ (life cycle) λ₯Ό μ§μνλ€.
μ΄λ¬ν λ©μλλ€μ ν μ€νΈ μμ±κ³Ό μ€ν λ°©λ²μ 컀μ€ν°λ§μ΄μ§ νκΈ° μν΄ μ€λ²λΌμ΄λ ν μ μλ€.
AnyFunSuite
λ₯Ό ν¬ν¨ν λͺ¨λ μ€μΉΌλΌ ν
μ€νΈ μ€νμΌμ μμ μ μΈ μ΄λ¦μ κ°λ ν
μ€νΈ μμ±μ κΆμ₯νκ³ μ μ€κ³λ¬λ€.
14.3 μΆ©λΆν μ 보λ₯Ό μ 곡νλ μ€ν¨ 보κ³
λ¨μΈλ¬Έμ΄ μ€ν¨νλ€λ©΄ νμΌμ΄λ¦, μ€ν¨ν λ¨μΈλ¬Έ μ€ λ²νΈ, μ λ³΄κ° λ΄κΈ΄ μ€λ₯λ©μΈμ§κ° μ€λ₯ λ³΄κ³ μ ν¬ν¨λμ΄μΌ νλ€.
scala> val width = 3
width: Int = 3
scala> assert(width == 2)
org.scalatest.exceptions.TestFailedException:
3 did not equal 2
λ¨μΈλ¬Έ μ€ν¨μ λ μμΈν μ 보λ₯Ό μνλ€λ©΄, μ€μΉΌλΌ ν μ€νΈμ Diagrams λ₯Ό μ¬μ©ν μ μλ€.
scala> assert(List(1, 2, 3).contains(4))
org.scalatest.exceptions.TestFailedException:
assert(List(1, 2, 3).contains(4))
| | | | | |
| 1 2 3 false 4
List(1, 2, 3)
μ€μΉΌλΌν
μ€νΈμ assert
λ©μλλ μ€λ₯ λ©μΈμ§μμ μ€μ κ²°κ³Όμ κΈ°λλλ κ²°κ³Όμ μ°¨μ΄λ₯Ό 보μ¬μ£Όμ§ μλλ€.
λ§μ½ μ΄λ€ λ©μλκ° λ°μμν¬ μ μλ μμΈλ₯Ό κ²μ¬νκ³ μΆλ€λ©΄, μ€μΉΌλΌν μ½νΈμ assertThrows λ©μλλ₯Ό λ€μκ³Ό κ°μ΄ μ¬μ©ν μ μλ€.
assertThrows[IllegalArgumentException] {
elem('x', -2, 3)
}
μ€κ΄νΈ λ΄μ μ½λκ° λ€λ₯Έ μμΈλ₯Ό λ°μμν€κ±°λ, μ΄λ€ μμΈλ λ°μμν€μ§ μλλ€λ©΄, assertThrows λ TestFailedException κ³Ό ν¨κ» μ¦μ λλ κ²μ΄λ€.
14.4 λͺ μΈλ‘ ν μ€νΈνκΈ°
λμ μ£Όλ κ°λ° (BDD: Behavior Driven Development) ν μ€νΈλ μ½λμ λμμ΄ μ¬λμ΄ μ½μ μ μλ λͺ μΈλ‘ μμ±νκ³ , μ½λκ° κ·Έ λͺ μΈμ λ°λΌ μ₯λνλμ§ νμΈνλ ν μ€νΈλ₯Ό μμ±νλλ° μ€μ μ λλ€.
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
class ElementSpec extends AnyFlatSpec with Matchers {
"A UniformElement" should
"have a width equal to the passed value" in {
val ele = elem ('x', 2, 3)
elem.width should be (2)
}
it should "have a height equal to the passed value" in {
val ele = elem('x', 2, 3)
ele.height should be (3)
}
it should "throw an IAE if passed a negative width" in {
an [IllegalArgumentException] should be thrownBy {
elem('x', -2, 3)
}
}
}
AnyFlatSpec
μμλ λͺ
μΈ μ (specifier clause) μ μ¬μ©ν΄ ν
μ€νΈλ₯Ό μμ±νλ€.
λ¨Όμ ν
μ€νΈ ν μ£Όμ μ λν΄ μ΄λ¦μ λ¬Έμμ΄λ‘ λΆμ΄λ κ²λΆν° μμνλ€.
κ·Έ λ€μ should
λ₯Ό λ£κ³ , κ·Έ λ€μ μ£Όμ μ μλμ μ€λͺ
νλ λ¬Έμμ΄μ΄ μ€κ³ , κ·Έ λ€μμ in
μ΄ λ°λΌμ¨λ€.
in
λ€μμλ μ€κ΄νΈ μμ μ§μ ν λμμ ν
μ€νΈνλ μ½λλ₯Ό μμ±νλ€.
μλ¦ ν λ 보λ₯΄ (Eric Torreborrre) κ° μ€μΉΌλΌλ‘ μμ±ν μ€νμμ€ λκ΅¬μΈ μ€νμ€2 (specs2) ν μ€νΈ νλ μμν¬λ BDD λ₯Ό μ§μνλ€.
BDD μ κ°μ₯ ν° μμ΄λμ΄ μ€ νλλ μ΄λ€ μννΈμ¨μ΄ μμ€ν μ λ§λ€μ§ κ²½μ νλ μ¬λ, κ·Έ μννΈμ¨μ΄λ₯Ό ꡬννλ μ¬λ, κ·Έλ¦¬κ³ κ·Έ μννΈμ¨μ΄κ° μ λ§λ¬΄λ¦¬ λμ΄ λμνλμ§λ₯Ό κ²°μ νλ μ¬λ μ¬μ΄μ μμ¬μν΅μ ν μ€νΈκ° λμμ€ μ μλ€λ κ²μ΄λ€.
import org.scalatest._
import org.scalatest.featurespec.AnyFeatureSpec
class TVSetSpec extends AnyFeatureSpec with GivenWhenThen{
Feature("TV power button")
Scenario("User presses power button when TV is off") {
Given("a TV set that is switched off")
When("the power button is pressed")
Then("the TV should switch on)
pending
}
}
AnyFeatureSpec
μ μννΈμ¨μ΄ μꡬμ¬νμ λν λνλ₯Ό λκΈ° μν΄ μ€κ³λμλ€.
μ΄λ ꡬ체μ μΈ νΉμ§ (feature) μ λ°νμΌ νκ³ , κ·Έλ° νΉμ§μ μλλ¦¬μ€ (scenario) μ λͺ
μν΄μΌ νλ€.
Given, When, Then μ ꡬ체μ μΈ κ°λ³ μλ리μ€μ λν λνμ μ΄μ μ λ§μΆλλ° λμμ μ€ μ μλ€.
pending
νΈμΆμ ν μ€νΈλ μ€μ λμμ΄ μμ§ κ΅¬νλμ§ μμλ€λ μ¬μ€μ λͺ μνλ€.
14.5 νλ‘νΌν° κΈ°λ° ν μ€νΈ
리컀λ λμ¨ (Rickard Nilsson) μ΄ μμ±ν μ€νμμ€ νλ μμν¬μΈ μ€μΉΌλΌμ²΄ν¬ (Scala Check) λ μ€μΉΌλΌλ‘ λ§λ€μ΄μ§ λ λ€λ₯Έ μ μ©ν ν μ€νΈ λꡬμ΄λ€.
μ€μΉΌλΌ 체ν¬λ μ½λκ° μ€μν΄μΌ νλ νλ‘νΌν°λ₯Ό λͺ μνκ² ν΄μ€λ€.
import org.scalatest.wordspec.AnyWordSpec
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
import org.scalatest.matchers.must.Matchers._
class ElementSpec extends AnyWorldSpec with ScalaCheckPropertyChecks {
"elem result" must {
"have passed width" in {
forAll { (w: Int) =>
whenever (x > 0) {
elem('x', w % 100, 3).width must equal (w % 100)
}
}
}
}
}
forAll
λ©μλ λ΄λΆμ elem ν©ν λ¦¬κ° μ§μΌμΌ νλ νλ‘νΌν°λ₯Ό κ²μ¬νλ€.
whenever (w > 0) {
elem('x', w % 100, 3).width must equal (w % 100)
}
whenever
μ μ μΌμͺ½ νΈμ μλ μμ΄ true
μΌ λλ§λ€ μ€λ₯Έμͺ½μ μλ μμ΄ true
κ° λμ΄μΌ ν¨μ λͺ
μνλ€.
μ€μΉΌλΌ 체ν¬λ νλ‘νΌν°μ λ§μ§ μλ κ°μ μ°ΎκΈ° μν΄ w
μ λ€μ΄κ° μ μλ κ°μ μ¬λ¬κ° μμ±νκ³ κ°κ°μ ν
μ€νΈνλ€.
μ€μΉΌλΌ 체ν¬κ° μλνλ λͺ¨λ κ°μ νλ‘ν°κ° λ§μ‘±νλ κ²½μ° ν
μ€νΈλ₯Ό ν΅κ³Όνκ³ , κ·Έλ μ§ μμΌλ©΄ μ€ν¨μ μμΈμ΄ λ κ°μ΄ λ€μ΄μλ TestFailedException
μ λΏμΌλ©° ν
μ€νΈκ° μ’
λ£λλ€.
abstract class Element {
def contents: Array[String]
def height: Int = contents.length
def width: Int = if (height == 0) 0 else contents(0).length
}
Element ν΄λμ€λ 10.3 μμ λ₯Ό λ°λ₯Έλ€.
μ°Έκ³ μλ£
νλ‘νΌν° κΈ°λ° ν μ€νΈλ‘ μΆμ² λ°μ Hedgehog
14.6 ν μ€νΈ μ‘°μ§κ³Ό μ€ν
μ€μΉΌλΌ ν μ€νΈμμλ μ€μνΈ (suite) μμ μ€μνΈλ₯Ό ν¬ν¨ μν΄μΌλ‘μ¨ ν° ν μ€νΈλ₯Ό μ‘°μ§ν νλ€.
μ΄λ μ΄λ€ μ€μνΈκ° μ€νλλ©΄ κ·Έ μμ ν μ€νΈ λΏλ§μ΄ μλλΌ λ΄λΆμ μλ μ€μνΈμ ν μ€νΈλ μ€νν¨μΌλ‘μ¨ λ΄ν¬λ λͺ¨λ μ€μνΈλ₯Ό μ€ννλ€.
ν° μ€μνΈλ Suite κ°μ²΄ νΈλ¦¬λ‘ ννν μ μλ€.
μλ νΉμ μλμΌλ‘ μ€μνΈλ₯Ό ν¬ν¨ μν¬μ μλ€.
μλ
nestedSuites
λ©μ€λλ₯Ό μ€λ²λΌμ΄λ νκ±°λ ν¬ν¨μν€κ³ μΆμ μμ±μμSuite
ν΄λμ€μ μμ±μμ μ λ¬- μ€μνΈκ°μ ν¬ν¨κ΄κ³λ₯Ό μν΄μ μΆκ° μμ±μλ₯Ό μ 곡
μλ
- μ€μΉΌλΌ ν
μ€νΈμ
Runner
μ ν¨ν€μ§ μ΄λ¦μ μ λ¬
14.7 κ²°λ‘
μλ°μμμ μ΅μν ν μ€νΈ λꡬμ μ₯μ μ μ΄λ¦΄μλ μκ³ , μ€μΉΌλΌν μ€νΈ, μ€μΉΌλΌμ²΄ν¬, μ€ν©μ€2 λ±μ μ€μΉΌλΌλ§μ μν΄ μ€κ³ν μλ‘μ΄ λꡬμ μ΄μ λ μ·¨ν μ μλ€.
Chapter 15 μΌμ΄μ€ ν΄λμ€μ ν¨ν΄ 맀μΉ
μΌμ΄μ€ ν΄λμ€ (Case Class) μ ν¨ν΄ λ§€μΉ (Pattern Match) λ μΌλ°μ μ΄κ³ μΊ‘μνλμ§ μλ λ°μ΄ν° ꡬ쑰λ₯Ό μμ±ν λ μ°μΈλ€.
15.1 κ°λ¨ν μ
μΌμ΄μ€ ν΄λμ€μ μ μ
abstract class Expr
case class Var(name: String) extends Expr
case class Number(num: Double) extends Expr
case class UnOp(operator: String, arg: Expr) extends Expr
case class BinOp(operator: String, left: Expr, right: Expr) extends Expr
μΌμ΄μ€ ν΄λμ€
ν΄λμ€ μ μΈμμ κ° μλΈ ν΄λμ€ μμ case λΌλ μμμκ° μμμ μ£Όμνλ€.
case
μμμλ μ€μΉΌλΌ μ»΄νμΌλ¬μκ² ν΄λΉ ν΄λμ€μ λ¬Έλ²μ μΌλ‘ νΈλ¦¬ν κΈ°λ₯ λͺκ°μ§λ₯Ό μΆκ°νλΌκ³ μ§μνλ€.
- μ»΄νμΌλ¬λ ν΄λμ€ μ΄λ¦κ³Ό κ°μ ν©ν 리 λ©μλλ₯Ό μΆκ°νλ€.
scala> val v = Var("x")
v: Var = Var(x)
ν©ν 리 λ©μλλ μ€μ²©ν΄μ κ°μ²΄λ₯Ό μμ±ν λ μ’λ€.
- μΌμ΄μ€ ν΄λμ€μ νλΌλ―Έν° λͺ©λ‘μ μλ λͺ¨λ μΈμμ μμμ μΌλ‘
val
μ λμ¬λ₯Ό λΆμΈλ€.
scala> v.name
res0: String = x
scala> op.left
res1: Expr = Number(1.0)
κ° νλΌλ―Έν°κ° ν΄λμ€μ νλλ λλ€.
- μ»΄νμΌλ¬λ μΌμ΄μ€ ν΄λμ€μ
toString
,hashCode
,equals
λ©μλμ μΌλ°μ μΈ κ΅¬νμ μΆκ°νλ€.
scala> println(op)
BinOp(+,Number(1.0),Var)
scala> op.right == Var("x")
res3: Boolean = true
μ€μΉΌλΌμμλ ==
μ μ¬μ©ν λΉκ΅λ₯Ό νμ equals
μ μμνλ€.
- μ»΄νμΌλ¬λ μ΄λ€ μΌμ΄μ€ ν΄λμ€μμ μΌλΆλ₯Ό λ³νν 볡μ¬λ³Έμ μμ±νλ
copy
λ©μλλ₯Ό μΆκ°νλ€.
μ΄ copy
λ©μλλ λν΄νΈ νλΌλ―Έν°μ μ΄λ¦μ λΆμΈ νλΌλ―Έν°λ₯Ό μ 곡νλ€.
scala> op.copy(operator = "-")
BinOp(-,Number(1.0),Var)
νμ§λ§ μΌμ΄μ€ ν΄λμ€μ κ°μ₯ ν° μ₯μ μ ν¨ν΄ 맀μΉλ₯Ό μ§μνλ€λ μ μ΄λ€.
ν¨ν΄ 맀μΉ
ν¨ν΄ 맀μΉλ μ€μΉΌλΌμμ ν¨μλ₯Ό λ¨μν μν€λκ²μ΄ ν΅μ¬
def simplifyTop(expr: Expr): Expr = expr match {
case UnOp("-", UnOp("-", e)) => e
case BinOp("+", e, Number(0)) => e
case BinOp("*", e, Number(1)) => e
case _ => expr
}
simplifyTop(UnOp("-", UnOp("-", Var("x"))))
// Var(x)
simplifyTop(BinOp("+", UnOp("-", Var("x")), Number(3)))
// BinOp(+,UnOp(-,Var(x)),Number(3.0)) ???
TODO
λ°©λ¬Έμ ν¨ν΄ μ μ¬μ©νμ¬ λμΌν κΈ°λ₯μ ꡬνν΄λ³΄μ
switch μ match μ λΉκ΅
match μμ μλ° μ€νμΌμ switch λ₯Ό μΌλ°νν κ²μ΄λ€.
μ€μΉΌλΌμ match μ μλ° switch μ°¨μ΄μ μ λ€μκ³Ό κ°λ€.
- μ€μΉΌλΌμ match λ ννμμ΄λ€. λ°λΌμ κ²°κ΄κ°μ λ΄λλλ€.
- μ€μΉΌλΌμ λμ ννμμ λ€μ μΌμ΄μ€λ‘ λΉ μ§μ§ μλλ€.
- match μ μ±κ³΅νμ§ λͺ»ν κ²½μ° MatchError μμΈκ° λ°μνλ€.
15.2 ν¨ν΄μ μ’ λ₯
μμΌλ μΉ΄λ ν¨ν΄
μ± μμ λ° μ€λͺ μ°Έκ³
μμ ν¨ν΄
μ± μμ λ° μ€λͺ μ°Έκ³
λ³μ ν¨ν΄
μ± μμ λ° μ€λͺ μ°Έκ³
λ³μ λλ μμ?
μ± μμ λ° μ€λͺ μ°Έκ³
μμ±μ ν¨ν΄
μ± μμ λ° μ€λͺ μ°Έκ³
μνμ€ ν¨ν΄
μ± μμ λ° μ€λͺ μ°Έκ³
νν ν¨ν΄
μ± μμ λ° μ€λͺ μ°Έκ³
νμ μ§μ ν¨ν΄
μ± μμ λ° μ€λͺ μ°Έκ³
νμ μκ±°
μ± μμ λ° μ€λͺ μ°Έκ³
λ³μ λ°μΈλ©
μ± μμ λ° μ€λͺ μ°Έκ³
15.3 ν¨ν΄ κ°λ
ν ν¨ν΄ μμ μ€μ§ νλ²λ§ λμμΌ νλ€. μ΄λ μ€μΉΌλΌκ° μ ν ν¨ν΄μΌλ‘ μ ννκΈ° λλ¬Έμ΄λ€.
scala> def simplifyAdd(e: Expr) = e match {
case BinOp("+", x, x) => BinOp("*", x, Number(2))
case _ => e
}
// error: x is already defined as value x
νμ§λ§ ν¨ν΄ κ°λ (pattern guard) λ₯Ό μ¬μ©νλ©΄ match ννμμ λ€μ μΈ μ μλ€.
scala> def simplifyAdd(e: Expr) = e match {
case BinOp("+", x, y) if x == y =>
BinOp("*", x, Number(2))
case _ => e
}
ν¨ν΄ κ°λλ ν¨ν΄ λ€μ μ€κ³ if
λ‘ μμνλ€.
15.4 ν¨ν΄ κ²ΉμΉ¨
ν¨ν΄ 맀μΉλ μ½λμ μλ μμλ₯Ό λ°λ₯Έλ€.
λ°λΌμ λͺ¨λ κ²½μ°λ₯Ό μ²λ¦¬νλ case λ¬Έμ΄ λ ꡬ체μ μΈ κ·μΉ λ€μμ μμΌ νλ€. (λ μ’μ λ²μλ₯Ό μ²λ¦¬νλ κ·μΉμ΄ μ νλμ΄μΌ νλ€.)
def simplifyBad(expr: Expr): Expr = expr match {
case UnOp(op, e) => UnOp(op, simplifyBad(e))
case UnOp("-", UnOp("-", e)) => e
}
// case UnOp("-", UnOp("-", e)) => e μ½λλ λλ¬ν μ μλ€.
15.5 λ΄μΈλ ν΄λμ€
μ»΄νμΌλ¬μ λμμ μ»μ΄ λͺ¨λ μΌμ΄μ€μ 맀μΉλ₯Ό κ°λ₯νλλ‘ λμΉ ν¨ν΄ μ‘°ν©μ΄ μμΌλ©΄ μλ €μ€λ€.
μΌμ΄μ€ ν΄λμ€λ₯Ό λ΄μΈλ ν΄λμ€ (sealed class) λ‘ λ§λ€λ©΄ κ·Έ ν΄λμ€μ κ°μ νμΌμ΄ μλ λ€λ₯Έ κ³³μμ μλ‘μ΄ μλΈ ν΄λμ€λ₯Ό λ§λ€ μ μλ€.
λ΄μΈλ ν΄λμ€λ₯Ό λ§λλ €λ ν΄λμ€ μμ sealed
λΌλ ν€μλλ₯Ό λ£μΌλ©΄ λλ€.
sealed abstract class Expr
case class Var(name: String) extends Expr
case class Number(num: Double) extends Expr
case class UnOp(operator: String, arg: Expr) extends Expr
case class BinOp(operator: String, left: Expr, right: Expr) extends Expr
μμ κ°μ΄ λ΄μΈλ ν΄λμ€λ₯Ό μ μν΄λκ³ μλμ κ°μ΄ λ§€μΉ μΌμ΄μ€λ₯Ό μμ±νλ€.
def describe(e: Expr): String = e match {
case Number(_) => "a number"
case Var(_) => "a variable"
}
λ€μκ³Ό κ°μ κ²½κ³ κ° λ ΈμΆ λλ€.
warning: match is not exhaustive!
missing combination UnOp
missing combination BinOp
λ§μ½ κ²½κ³ λ₯Ό μμ κ³ μΆλ€λ©΄ λλ¨Έμ§ μΌμ΄μ€λ₯Ό λ€ λ§€μΉμμΌλλλ€.
def describe(e: Expr): String = e match {
case Number(_) => "a number"
case Var(_) => "a variable"
case _ => throw new RuntimeException
}
λ μΈλ ¨λ λ°©λ²μ @unchecked
μ΄λ
Έν
μ΄μ
μ μΆκ°νλ κ²μ΄λ€.
μ΄ @unchecked
μ΄λ
Έν
μ΄μ
μ ν¨ν΄ 맀μΉμ λͺ¨λ ν¨ν΄μ λ€ λ€λ£¨λμ§ κ²μ¬νλ μΌμ μλ΅νλ€.
15.6 Options νμ
μ€μΉΌλΌμλ Option μ΄λΌλ νμ€ νμ μ΄ μλ€. μ΄ νμ μ μ νμ μΈ κ°μ νννλ©° λκ°μ§ ννκ° μλ€.
λ§μ½ x
κ° μ€μ κ°μ΄λΌλ©΄ Some(x)
λΌλ ννλ‘ κ°μ΄ μμμ ννν μ μλ€. λ°λλ‘ κ°μ΄ μμΌλ©΄ None
μ΄λΌλ κ°μ²΄κ° λλ€.
scala> def show(x: Option[String]) = x match {
case Some(s) => s
case None => "?"
}
μ€μΉΌλΌμμλ μ νμ μΈ κ°μ λνλ΄κΈ° μν΄ Option
μ μ¬μ©νλλ‘ κΆμ₯νλ€.
15.7 ν¨ν΄μ μ΄λμμλ
λ 립μ μΈ match ννμλΏ μλλΌ, μ€μΉΌλΌμ μ¬λ¬κ³³μμ ν¨ν΄μ μ¬μ©ν μ μλ€.
λ³μ μ μμμ ν¨ν΄ μ¬μ©νκΈ°
val
μ΄λ var
λ₯Ό μ μν λ μλ³μ λμ μ ν¨ν΄μ μ¬μ©ν μ μλ€.
scala> val myTuple = (123, "abc")
myTuple: (Int, java.lang.String) = (123,abc)
scala> val (number, string) = myTuple
number: Int = 123
string: java.lang.String = abc
λ€μκ³Ό κ°μ΄ ꡬ쑰ν΄μ²΄ ꡬ문과 κ°μ΄(?) μ¬μ© κ°λ₯νλ€.
scala> val exp = new BinOp("*", Number(5), Number(1))
exp: BinOp = BinOp(*,Number(5.0),Number(1.0))
scala> val BinOp(op, left, right) = exp
op: String = *
left: Expr = Number(5.0)
right: Expr = Number(1.0)
case λμ΄ν΄μ λΆλΆ ν¨μ λ§λ€κΈ°
val withDefault: Option[Int] => Int = {
case Some(x) => x
case None => 0
}
μλ case
λ¬Έμ λΆλΆ ν¨μμ²λΌ μ¬μ© κ°λ₯νλ€.
scala> withDefault(Some(10))
// Int = 10
scala> withDefault(None)
// Int = 0
μ΄λ¬ν κΈ°λ₯μ μμΉ΄ μ‘ν° (akka actors) λΌμ΄λΈλ¬λ¦¬μμ μ μ©νλ°, case λ₯Ό λμ΄νμ¬ receive λ©μλ μ μλ₯Ό κ°λ₯μΌ νλ€.
μ μν μ μ case λμ΄μ λΆλΆ ν¨μ (partial function) μ΄ μ²λ¦¬νμ§ μλ κ°μ μ λ¬ν΄μ νΈμΆνλ©΄ μ€ν μμ μ μμΈκ° λ°μνλ€.
val second: List[Int] => Int = {
case x :: y :: _ => y
}
// warning: match is not exhaustive!
// missing combination Nil
μ μ½λλ μμλ₯Ό 3κ°λ₯Ό λκΈ°λ©΄ ν΅κ³Όνμ§λ§ λΉ λ¦¬μ€νΈλ₯Ό λκΈ°λ©΄ μ€ν¨νλ€.
μ΄λ¬ν μ΄μ ν΄κ²°μ μν΄ isDefinedAt
λ©μλλ₯Ό μ 곡νλλ°, isDefinedAt
λ©μλλ λΆλΆ ν¨μκ° μ΄λ€ κ°μ λν΄ κ²°κ΄κ°μ μ μνκ³ μλμ§ μλ €μ€λ€.
second.isDefinedAt(List(5,6,7))
// Boolean = true
second.isDefinedAt(List())
// Boolean = false
for ννμμμ ν¨ν΄ μ¬μ©νκΈ°
for ((country, city) <- capitals)
println("The capital of "+ country +" is "+ city)
// The capital of France is Paris
// The capital of Japan is Tokyo
μμ κ°μ΄ for
ννμ μμ ν¨ν΄μ μ¬μ©ν μ μλ€.
15.8 볡μ‘ν μμ
μμ μ½λ μ€λͺ
15.9 κ²°λ‘
μΌμ΄μ€ ν΄λμ€μ ν¨ν΄λ§€μΉλ₯Ό μ¬μ©νλ©΄ κ°μ²΄μ§ν₯μμ μ§μνμ§ μλ κ°κ²°ν ννλ²μ μ΄μ μ λ릴μ μλ€.