2μ£Όμ°¨ (6 ~ 10 Chapter)
Chapter 06 ν¨μν κ°μ²΄
μ§κΈκΉμ§ μ€μΉΌλΌμ κΈ°λ³Έμ μΈ λ΄μ©μ μ΄ν΄νλ€λ©΄, μ΄μ λ μ’ λ μμ ν κΈ°λ₯μ κ°μΆ μ€μΉΌλΌμ ν΄λμ€ μμ±λ²μ μμλ³Ό μ°¨λ‘μ΄λ€.
ν΄λμ€ νλΌλ―Έν°, μμ±μ, λ©μλ, μ°μ°μ, λΉκ³΅κ° λ©€λ², μ€λ²λΌμ΄λ, μ κ²° 쑰건 νμΈ, μ€λ²λ‘λ, μκΈ° μ°Έμ‘° κ°μ μ€μΉΌλΌμ κ°μ²΄μ§ν₯ νλ‘κ·Έλλ° μμλ₯Ό μ€λͺ ν κ²μ΄λ€.
6.1 λΆμ ν΄λμ€ λͺ μΈ
μ΄λ²μ₯ λΆν°λ λΆλͺ¨ ν΄λμ€λ₯Ό λ§λ€μ΄ μ§νν΄λ³΄κ² λ€.
μΌλ°μ μΌλ‘ μνμμμ λΆμμ μ°μ°μ μ΄ν΄λ³΄λ©΄ κ° λΆλͺ¨μ μΌμΉνλ μμ μ ν΅ν΄ μ°μ°μ μννλ€.
λ°λΌμ μνμ λΆμλ₯Ό μ½λμ μΌλ‘ ν΄μνλ©΄ λ³κ²½ κ°λ₯ν μνκ° μμμ μ μ μλ€.
λ€μμ μ΄λ₯Ό μ½λλ‘ ννν λ°©μμ΄λ€.
val oneHalf = new Rational(1, 2)
val twoThirds = new Rational(2, 3)
(oneHalf / 7) + (1 - twoThireds)
6.2 Rational μμ±
μνμ λΆμμμ μ²λΌ Rational
κ°μ²΄λ₯Ό μ¬μ©νλλ‘ λ³κ²½ λΆκ°λ₯ν κ°μ²΄λ‘ μ¬μ©νμ.
class Rational(n: Int, d: Int)
ν΄λμ€ μ΄λ¦μΈ Rational
λ€μ κ·Έ μμλ n
, d
μ΄λΌλ μλ³μκ° μλ€.
μ΄λ₯Ό ν΄λμ€ νλΌλ―Έν° (class parameter) λΌκ³ λΆλ₯Έλ€.
ν΄λμ€ νλΌλ―Έν°μ κ°μ λ₯ μΈμλ₯Ό λ°λ μ£Ό μμ±μ (primary constructor) λ₯Ό λ§λ λ€.
λ³κ²½ λΆκ°λ₯ν κ°μ²΄μ μ₯λ¨μ
λ³κ²½ λΆκ°λ₯ν κ°μ²΄μ μ₯μ μ λ§μ§λ§ κ°μ₯ ν° λ¨μ μ κ·Έ μ리μμ μνλ₯Ό λ°λ‘ λ³κ²½νλ©΄ κ°λ¨νλ°
κ±°λ κ·Έλν κ°μ²΄λ₯Ό 볡μ¬ν΄μΌ νλ κ²½μ°μ²λΌ λ§μ λΉμ©μ΄ λλ μμ μ μνν λ ν΄λΉ μκ³ λ¦¬μ¦μ νννκΈ°μλ μ΄λ €μ°λ©° μ±λ₯μμ μ΄μκ° λ°μνκΈ°λ νλ€.
λλ¬Έμ μ€μΉΌλΌμμλ λ³κ²½ λΆκ°λ₯νκ²κ³Ό λ³κ²½ κ°λ₯νκ²μ νμ κ°μ΄ μ 곡νλ€.
6.3 toString λ©μλ λ€μ ꡬννκΈ°
μλ°μ κ°μ΄ toString
λ©μλλ₯Ό Rational ν΄λμ€μ μΆκ°νλ©΄ κΈ°μ‘΄ ꡬνμ μ€λ²λΌμ΄λ© ν μ μλ€.
class Rational(n: Int, d: Int) {
override def toString = s"$n/$d"
}
μΈν°ν리ν°μμλ λ€μκ³Ό κ°μ΄ νμΈμ΄ κ°λ₯νλ€.
val x = new Rational(1, 3)
// x: Rational = 1/3
val y = new Rational(5/7)
// y: Rational = 5/7
6.4 μ κ²° 쑰건 νμΈ
require
λ μ 결쑰건μ λ§λ€κΈ° μν μ¬λ¬κ°μ§ λ°©λ² μ€ νλμ΄λ©°
μ£Ό μμ±μμ μλ νλΌλ―Έν°λ₯Ό κ²μ¦ν λ μ μ©νλ€.
class Rational(n: Int, d: Int) {
require(d != 0)
override def toString = s"$n/$d"
}
require
λ©μλλ μΈμλ‘ Boolean
κ°μ λ°λλ°, μ΄ κ°μ΄ μ°Έ (true) μ΄λ©΄ require
κ°μ΄ μ μμ μΌλ‘ λλκ³ λ€μμΌλ‘ μ§ννλ€.
λ§μ½ μ λ¬ λ°μ κ°μ΄ κ±°μ§ (false) μ΄λΌλ©΄ IllegalArgumentException
μμΈκ° λ°μνμ¬ κ°μ²΄ μμ±μ λ§λλ€.
6.5 νλ μΆκ°
class Rational(n: Int, d: Int) {
require(d != 0)
override def toString = s"$n/$d"
def add(that: Rational): Rational =
new Rational(n * that.d + that.n * d, d * that.d)
}
μ μ½λλ μ»΄νμΌ μ€λ₯κ° λ°μνλ€.
Rational κ°μ²΄ λΆλͺ¨, λΆμ κ°μ μ κ·ΌνκΈ° μν΄μλ νλλ‘ λ§λ€μ΄μΌ νλ€.
νλλ₯Ό μΆκ°νμ¬ ν΄κ²°ν ννλ λ€μκ³Ό κ°λ€.
class Rational(n: Int, d: Int) {
require(d != 0)
val numer: Int = n
val denom: Int = d
override def toString = s"$n/$d"
def add(that: Rational): Rational =
new Rational(
numer * that.denom + that.numer * denom,
denom * that.denom
)
}
μ΄μ κ³Ό λ¬λ¦¬ κ°μ²΄ λ°κΉ₯μμ νλλ₯Ό ν΅ν΄ λΆμμ λΆλͺ¨κ°μ μ κ·Όν μ μλ€.
6.6 μκΈ° μ°Έμ‘°
μ€νμ€μΈ λ©μλμ νΈμΆ λμ μΈμ€ν΄μ€μ λν μ°Έμ‘°λ₯Ό μκΈ° μ°Έμ‘° (self reference) λΌκ³ νλ€.
def lessThan(that: Rational) =
this.numer * that.denom < that.numer * this.denom
μ μ½λμμ this
λ₯Ό λΉΌκ³ numer
λΌκ³ μ¨λ κ°λ€.
6.7 보쑰 μμ±μ
μ€μΉΌλΌμμ μ£Ό μμ±μκ° μλ λ€λ₯Έ μμ±μλ₯Ό 보쑰 μμ±μ (auxiliary constructor) λΌκ³ νλ€.
class Rational(n: Int, d: Int) {
require(d != 0)
val numer: Int = n
val denom: Int = d
def this(n: Int) = this(n, 1) // 보쑰 μμ±μ
override def toString = s"$n/$d"
def add(that: Rational): Rational =
new Rational(
numer * that.denom + that.numer * denom,
denom * that.denom
)
}
μ€μΉΌλΌμμ 보쑰 μμ±μλ def this(...)
λΌκ³ μμνλ€.
λͺ¨λ μμ±μ νΈμΆμ κ±°μ¬λ¬ μ¬λΌκ°λ©΄ κ²°κ΅ μ£Ό μμ±μλ₯Ό νΈμΆνκ² λ§λλ ν¨κ³Όκ° μλ€.
6.8 λΉκ³΅κ° νλμ λ©μλ
μ΅λ 곡μ½μλ₯Ό κ³μ°νλ λΉκ³΅κ° νλμ λ©μλλ₯Ό μΆκ°νμ
class Rational(n: Int, d: Int) {
require(d != 0)
private val g = gcd(n.abs, d.abs)
val numer: Int = n
val denom: Int = d
def this(n: Int) = this(n, 1) // 보쑰 μμ±μ
override def toString = s"$n/$d"
def add(that: Rational): Rational =
new Rational(
numer * that.denom + that.numer * denom,
denom * that.denom
)
}
첫 μ€μ λ±μ₯νλ g
μ μ΄κΈ°ν μ½λ gcd(n.abs, d.abs)
λ λ€λ₯Έ λ μ΄κΈ°ν μ½λλ³΄λ€ λ¨Όμ μ€νλλ€.
λλ¬Έμ μ΅λ곡μ½μ g
λ‘ λλ κ°μ΄ numer
, denom
λ₯Ό μ½λΆμνλ‘ μ΄κΈ°ν μμΌμ€λ€.
6.9 μ°μ°μ μ μ
μνμ κΈ°νΈ +
λ λ©μλ μ΄λ¦μ μ μνλ©΄ add λ©μλλ₯Ό λ체ν μ μλ€.
def + (that: Rational): Rational =
new Rational(
numer * that.denom + that.numer * denom,
denom * that.denom
)
λ§μ°¬κ°μ§λ‘ κ³±μ
μ°μ°μμΈ *
λν times λ©μλλ₯Ό λ체ν μ μλ€.
def * (that: Reational): Rational =
new Rational(numer * that.numer, denom * that.denom)
6.10 μ€μΉΌλΌμ μλ³μ
μμ«μ μλ³μ (alphanumeric identifier)
- λ¬Έμλ λ°μ€ (_) λ‘ μμνλ€.
κ°νΉ λ°μ€κ³Όλ‘ λλλ μλ³μμΌλ λ€μκ³Ό κ°μ μλ¬λ₯Ό λ°μ μν¬μ μλ€.
val name_:Int = 1
μ κ²½μ° name_:Int
λ₯Ό λ³μλͺ
μΌλ‘ μ»΄νμΌ νλ € νκΈ° λλ¬Έμ μ½λ‘ μμ 곡백μ νλ λμ΄ λ€μκ³Ό κ°μ΄ μμ±ν΄μΌ νλ€.
val name_ :Int = 1
μ°μ°μ μλ³μ (operator identifier)
νλ μ΄μμ μ°μ°μ λ¬Έμλ‘ μ΄λ£¨μ΄μ Έ μλ€.
+ ++ ::: <?> :->
μλ₯Ό λ€λ©΄ :->
λ λ΄λΆμ μΌλ‘ $colon$minus$grater
λ‘ λ³νλλ€.
μλ°μμ μ¬μ©νλ €κ³ νλ€λ©΄ λ΄λΆ λ³ν μ΄λ¦μ μμμΌ νλ€.
νΌν© μλ³μ (mixed identifier)
μλ¬Έκ³Ό μ«μλ‘ μ΄λ€μ§ μλ³μ λ€μ λ°μ€μ΄ μ€κ³ κ·Έ λ€μ μ°μ°μ μλ³μκ° μ¨λ€.
myvar_=
리ν°λ΄ μλ³μ (iteral identifier)
μλ μ½λμ²λΌ μλ°μ΄ν (`)λ‘ λλ¬μΌ μμμ λ¬Έμμ΄μ΄λ€.
`x` `<clinit>` `yield`
λ°νμμ΄ μΈμν μ μλ μ΄λ€ λ¬Έμμ΄μ΄λΌλ μλ°μ΄ν μ¬μ΄μ λ£μ μ μλ€λκ² ν΅μ¬μ΄λ€.
μμ€ν μμ½μ΄λ₯Ό 무μν μ μλ λ°©λ²μΌλ‘ μμΈλ€.
Thread.`yield`()
6.11 λ©μλ μ€λ²λ‘λ
μ€μΉΌλΌμμ μ²λ¦¬νλ μ€λ²λ‘λ λ©μλλ μλ°μ κ±°μ μ μ¬νλ€.
μ€μΉΌλΌλ μ€λ²λ‘λν λ©μλ μ€ μΈμμ μ μ μΈ νμ κ³Ό κ°μ₯ μ μΌμΉνλ λ²μ μ μ ννλ€.
λ§μ½ μΌμΉνλ κ²°κ³Όκ° μμ κ²½μ° μ»΄νμΌλ¬λ ambiguous reference
μ€λ₯λ₯Ό λ
ΈμΆνμ¬ λͺ¨νΈν μ°Έμ‘°λΌλ μ¬μ€μ μλ¦°λ€.
6.12 μμμ νμ λ³ν
μμμ νμ λ³νμ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ’ λ μ μ°νκ³ μ¬μ©νκΈ° νΈλ¦¬νκ² λ§λ€μ΄μ£Όλ μμ£Ό κ°λ ₯ν κΈ°λ²μ΄λ€.
νμ§λ§ λ무λλ κ°λ ₯ν΄ μλͺ» μ¬μ©νκΈ°λ νλ€.
μ°μ°μ μλ³μλ₯Ό μ΄μ©νμ¬ r * 2
ννμ μ¬μ©ν μ μμ§λ§ 2 * r
μ ννμ μ€λ₯λ₯Ό λ°μ μν¨λ€.
μ΄λ μμμ νμ
μΌλ‘ λ³ννλ κ³Όμ μμ r * 2
λ r.*(2)
λ‘ λ°λκ² λλ©° 2 * r
λ 2.*(r)
λ‘ λ³νλμ΄ Int ν΄λμ€λ Rational
μΈμλ₯Ό λ°λ κ³±μ
λ©μλκ° μκΈ° λλ¬Έμ΄λ€.
6.13 μ£Όμμ¬ν
μ€μΉΌλΌλ μ½κ² μ¬μ©ν μ μλ λΌμ΄λΈλ¬λ¦¬ μ€κ³λ₯Ό ν μ μλ λ§κ°ν κΆνμ μ£Όμ§λ§ λ―Έμνκ² μ¬μ©νλ©΄ μ°μ°μ λ©μλμ μμμ νμ λ³ν λͺ¨λ ν΄λΌμ΄μΈνΈ μ½λλ₯Ό μ½κ³ μ΄ν΄νκΈ° νλ€κ² λ§λ λ€.
λΌμ΄λΈλ¬λ¦¬λ₯Ό μ€κ³νλ©° νμ μΌλμ λμ΄μΌ ν λͺ©νλ λ¨μν ν΄λΌμ΄μΈνΈ μ½λλ₯Ό κ°κ²°νκ² νλκ² λΏλ§μ΄ μλλΌ, κ°λ μ±μ λμ΄κ³ μ΄ν΄νκΈ° μ½κ² λ§λλ λ²μ΄λ€.
6.14 κ²°λ‘
λ€μμ₯μμλ Rational ν΄λμ€μ λλ° κ°μ²΄μ μμμ νμ λ³νμ λ£μ΄μ νΈλ¦¬νκ² μ¬μ©κ°λ₯ν μ€μ½νλ‘ λΆλ¬μ¬ μ μκ² νλ λ°©λ²μ μ€λͺ νκ² λ€.
Chapter 07 λ΄μ₯ μ μ΄ κ΅¬λ¬Έ
μ€μΉΌλΌμ λ΄μ₯ μ μ΄ κ΅¬λ¬Έμ λͺκ°μ§ μλ€.
- if
- while
- for
- try
- match
- ν¨μ νΈμΆ (function call)
μ€μΉΌλΌμ μ μ΄ κ΅¬λ¬Έμ μκ° μ μ μ΄μ λ μ€κ³ μ΄κΈ°λΆν° ν¨μ 리ν°λ΄μ ν¬ν¨νκΈ° λλ¬Έμ΄λ€.
νλ‘κ·Έλ¨ μ 체λ₯Ό κ°μ κ³μ°νλ κ΄μ μμ λ°λΌλ³΄κ³ νλ‘κ·Έλ¨ κ΅¬μ±μμ λν κ°μ λμΆν΄μΌ νλ€λ ν¨μ μΈμ΄μ μ κ·Όμ μ±μ©ν κ²°κ³Όμ΄λ€.
7.1 if ννμ
μ€μΉΌλΌμ if ννμμ κ°μ λ΄λκΈ° λλ¬Έμ λ κ°κ²°νκ² μ½λ μμ±μ΄ κ°λ₯νλ€.
val filename =
if (!args.isEmpty) args(0)
else "default.txt"
μ μ½λλ μ§μ§ μ₯μ μ var
μ΄ μλ val
μ μ¬μ©νλ€λ μ μ΄λ€.
var
μ΄ μλval
μ μ¬μ©ν¨μ μμ΄μ μ₯μ μ λμΌμ± μΆλ‘ (equational reasoning) μ΄ λμ± μ 리νλ€.
λΆμν¨κ³Όκ° μκΈ° λλ¬Έμ κ°μ λμΆνλ ννμκ³Ό λμΌνλ€.
val
μ μ¬μ©ν κΈ°νλ₯Ό λ Έλ¦¬λ©΄ μ½λλ₯Ό λ κ°λ μ±μ΄ λκ³ λ¦¬νν λ§ νκΈ° μ¬μμ§λ€.
7.2 while 루ν
while
루νλ κ²°κ³Όκ° νΉμ κ°μ΄ μλκΈ° λλ¬Έμ μμν ν¨μν μΈμ΄λ μ΄λ₯Ό μ’
μ’
μ μΈνκ³€ νλ€.
νμ§λ§ κ°νΉ λͺ
λ Ήν ν΄λ²μ΄ κ°λ
μ±μ΄ λ°μ΄λκΈ° λλ¬Έμ νΉμ μ‘°κ±΄μ΄ λ°λλκΉμ§ μ ν΄μ§ μ μ°¨λλ‘ λ°λ³΅νλ μκ³ λ¦¬μ¦μ μμ±νλ€κ³ νλ©΄ while
루νκ° λμμ΄ λ μ μλ€.
μΌλ°μ μΌλ‘ while
루νλ var
λ³μμ λ§μ°¬κ°μ§λ‘ μ΅λν μ κ² μ¬μ©νκΈ° μν΄ λ
Έλ ₯νλκ²μ κΆμ₯νλ€.
νΉλ³ν while
μ΄λ do-while
루νλ₯Ό μ¬μ©ν μΆ©λΆν μ΄μ κ° μλ€λ©΄ μ¬μ©νμ§ μλκ²μ κΆμ₯νλ€.
7.3 for ννμ
μ€μΉΌλΌμ for
ννμμ λ°λ³΅ μ²λ¦¬λ₯Ό μν λ§λ₯ ννμμ΄λ€.
컬λ μ μ΄ν°λ μ΄μ
for
λ‘ ν μ μλ κ°μ₯ κ°λ¨ν μΌμ λͺ¨λ μμλ₯Ό μ΄ν°λ μ΄μ
νλ κ²μ΄λ€.
val fileHere = (new java.io.File(".")).listFiels
for (file <- filesHere)
println(file)
μ λλ μ΄ν° (generator) λΌκ³ λΆλ₯΄λ file <- filesHere
λ¬Έλ²μ μ΄μ©ν΄ filesHere μμλ₯Ό μ΄ν°λ μ΄μ
νλ€.
μ΄ν°λ μ΄μ
λμ κ°μ λ²μμμ μ΅λκ°μ μ μΈνκ³ μΆλ€λ©΄ to
λμ until
μ μ¬μ©νλ€.
for (i <- 1 until 4)
println("Iteration " + i)
Iteration 1
Iteration 2
Iteration 3
νν°λ§
for
ννμμ νν° (filter) μ μΆκ°νλ©΄ μ 체 컬λ μ
μμ μΌλΆλ§ μ¬μ©ν μ μλ€.
val filesHere = (new java.io.File(".")).listFiles
for (file <-filesHere if file.getName.endsWith(".scala))
println(file)
λ§μ½ μ¬λ¬κ°μ νν°λ₯Ό μ μ©νλ €λ©΄ λ€μκ³Ό κ°μ΄ μ¬μ©νλ©΄ λλ€.
for (
file <- filesHere
if file.isFile
if file.getName.endsWith(".scala")
) println(file)
μ€μ²© μ΄ν°λ μ΄μ
2κ°μ 루νλ₯Ό μ€μ²©ν 리μ€νΈλ μ¬λ¬κ°μ <-
μ μ μ΄μ©νμ¬ μ€μ²©λ£¨νλ₯Ό μμ±ν μ μλ€.
def fileLines(file: java.io.File) =
scala.io.Source.fromFile(file).getLines().toArray
def grep(pattern: String) =
for (
file <- filesHere
if file.getName.endsWith(".scala");
line <- fileLines(file)
if line.trim.matches(pattern)
) println(s"$file: ${line.trim}")
grep(".*gcd.*")
λ°κΉ₯μͺ½ 루νλ filesHere
λ΄μ .scala
λ‘ λλλ νμΌμ
μμͺ½ 루νλ λ°κΉ₯루νμμ μ»μ file
μ fileLines(file)
μ νΈμΆν κ²°κ³Όλ₯Ό μ΄ν°λ μ΄μ
νλ€.
μνλ€λ©΄ μ€κ΄νΈλ₯Ό μ¬μ©νμ¬ μ λλ μ΄ν°μ νν°λ₯Ό κ°μΈλ λλ€.
μ€κ΄νΈλ₯Ό μ¬μ©νλ€λ©΄ μ€μΉΌλΌ μ»΄νμΌλ¬κ° μΈλ―Έμ½λ‘ μ μΆλ‘ νκΈ° λλ¬Έμ, κ΄νΈλ₯Ό μ¬μ©ν λ μ¨μΌλ§ νλ μΈλ―Έμ½λ‘ μ μ κ±°ν μ μλ€.
for μ€μ λ³μ λ°μΈλ© νκΈ°
μ μ½λμμ line.trim
μ΄λΌλ ννμμ λ°λ³΅νλλ° μ΄λ₯Ό λ³μλ‘ λ°μΈλ©νμ¬ μ²λ¦¬ κ°λ₯νλ€.
def fileLines(file: java.io.File) =
scala.io.Source.fromFile(file).getLines().toArray
def grep(pattern: String) =
for (
file <- filesHere
if file.getName.endsWith(".scala");
line <- fileLines(file)
trimmed = line.trim
if trimmed.matches(pattern)
) println(s"$file: ${trimmed}")
grep(".*gcd.*")
μλ‘μ΄ μ»¬λ μ λ§λ€μ΄λ΄κΈ°
μ΄ν°λ μ΄μ μ 맀 λ°λ³΅ λ¨κ³μ κ²°κ³Όλ₯Ό μ μ₯νκΈ° μν κ°μ λ§λ€ μ μλ€.
for
ννμμ λ³Έλ¬Έ μμ yield
λΌλ ν€μλλ₯Ό μ¬μ©νλ€.
def scalaFiles =
for {
file <- filesHere
if file.getName.endsWith(".scala")
} yield file
μ μ½λλ for ννμμ μνν λλ§λ€ κ° (file) μ νλμ© λ§λ€μ΄λΈλ€.
7.4 try ννμμΌλ‘ μμΈ λ€λ£¨κΈ°
νΈμΆν λ©μλκ° λ³λ€λ₯Έ μ²λ¦¬λ₯Ό νμ§ μκ³ μ’ λ£νλ©΄ ν΄λΉ λ©μλλ₯Ό νΈμΆν λ©μλ, μ¦ νΈμΆμμ νΈμΆμ λ©μλλ‘ μμΈλ₯Ό μ ννλ€.
μ΄λ₯Ό λ°©μ§νκΈ° μν΄ try ννμμΌλ‘ μ²λ¦¬νλ€.
μμΈ λ°μ μν€κΈ°
μλ°μ λμΌνκ² throw
ν€μλλ₯Ό μ΄μ©νμ¬ μμΈλ₯Ό λμ§λ€.
throw new IllegalArgumentException
val half =
if (n % 2 == 0)
n / 2
else
throw new RuntimeException("n must be even")
μμΈλ Nothing
μ΄λΌλ νμ
μ κ°λλ€.
λ°μν μμΈ μ‘κΈ°
ν¨ν΄ λ§€μΉ (pattern match)λ₯Ό μ΄μ©νμ¬ λ°μν μμΈλ₯Ό μ‘λλ€.
try {
val f = new FileReader("input.txt")
} catch {
case e: FileNotFoundException => // νμΌμ λͺ» μ°Ύλ κ²½μ° μ²λ¦¬
case e: IOException => // κ·Έ λ°μ IO μ€λ₯ μ²λ¦¬
}
finally μ
ννμμ κ²°κ³Όκ° μ΄λ»λ νΉμ μ½λλ₯Ό λ°λμ μννκ³ μΆμ κ²½μ° μ¬μ©
try {
// νμΌμ μ¬μ©νλ€.
} finally {
file.close()
}
μ€μΉΌλΌμμλ λμΌν λͺ©μ μ μ’ λ κ°κ²°νκ² λ¬μ±νκΈ° μν΄, λΉλ €μ£ΌκΈ° ν¨ν΄ (loan pattern) μ΄λΌλ κΈ°λ²μ μ¬μ©ν μ μλ€.
κ° λ§λ€μ΄λ΄κΈ°
finally ꡬ문μμλ κ°μ λ°ννμ§ μλ κ² μ΅μ μ΄λ€.
finally μ μ κ²°κ΄κ°μ λ§λ€μ΄ λ΄κΈ° 보λ€λ νμΌμ λ«κ±°λ μ 리νλ μμ μ νλλ± λΆμν¨κ³Όλ₯Ό μ 곡νλ λ°©λ²μ΄λΌκ³ μκ°νλκ² μ’λ€.
7.5 match ννμ
μ€μΉΌλΌμ match
ννμμ μ¬ν μΈμ΄μ swtich
λ¬Έκ³Ό μ μ¬νκ² λ€μμ λμ (alternative) μ€ νλλ₯Ό μ ννκ² ν΄μ€λ€.
val firstArg = if (args.length > 0) args(0) else ""
firstArg match {
case "salt" => println("pepper")
case "chips" => println("salsa")
case "eggs" => println("bacon")
case _ => println("huh?")
}
λͺ¨λ case λ§λ€ break λ¬Έμ΄ μ묡μ μΌλ‘ μμ΄μ, break λ¬Έμ΄ μμ΄λ λ€μ μ νμΌλ‘ λμ΄κ°μ§ μλλ€.
7.6 break μ continue λ¬Έ μμ΄ μ΄κΈ°
ν¨μ 리ν°λ΄μ μ₯μ μ νμ©νλ©΄ break
λ continue
μμ΄ λ κ°κ²°ν μ½λ μμ±μ΄ κ°λ₯νλ€.
λ§μ½ κ·Έλλ break
λ¬Έμ΄ νμνλ€ μκ°λλ©΄ scala.util.control
μ μλ Breaks
ν΄λμ€μμ break λ©μλλ₯Ό μ 곡νλ€.
import scala.util.control.Breaks._
import java.io._
val in = new BufferedReader(new InputStreamReader(System.in))
breakable {
while (true) {
println("? ")
if (in.readLine() == "") break
}
}
7.7 λ³μ μ€μ½ν
μ€μΉΌλΌμμ λ³μμ μ μνλ μ€μ½ν (scope) λ₯Ό κ°μ§λ€.
μλ°μμ ν΅μ©λλ μ§μλ³μ (local variable) κ°λ μ κ°μ§λ€.
λ³μλ€μ΄ λ§ κ·Έλλ‘ ν¨μ λ΄μ μ§μμ μΌλ‘ μ‘΄μ¬νλ©°, ν¨μκ° νΈμΆλ λλ§λ€ μλ‘μ΄ μ§μλ³μλ₯Ό λ§λ€μ΄μ μ¬μ©νλ€.
val a = 1;
{
val a = 2;
{
println(a)
}
}
2
μ€κ΄νΈλ₯Ό μ¬μ©νμ¬ μ€μ½νλ₯Ό μλ‘ λ§λ€ μ μλ€.
7.8 λͺ λ Ήν μ€νμΌ μ½λ 리νν λ§
ν¨μν λ°©μμΌλ‘ κ³°μ ν λ§λ€κΈ°
def makeRowSeq(row: Int) =
for (col <- 1 to 10) yield {
val prod = (row * col).toString
val padding = " " * (4 - prod.length)
padding + prod
}
def makeRow(row: Int) = makeRowSeq(row).mkString
def multiTable() = {
val tableSeq =
for (row <- 1 to 10)
yield makeRow(row)
tableSeq.mkString("\n")
}
7.9 κ²°λ‘
μ€μΉΌλΌμ λ΄μ₯ μ μ΄ κ΅¬μ‘°λ κ·Έ μλ μ μ§λ§ μνμ μ λλ‘ μννλ€.
λͺ λ Ήν μΈμ΄μ μ‘΄μ¬νλ ꡬ문과 μ μ¬ν μνμ μννμ§λ§, κ°μ΄ κ²°κ³Όκ° λλλ‘ μλνκΈ° λλ¬Έμ ν¨μν μ€νμΌλ‘λ μμ±μ΄ κ°λ₯νλ€.
Chapter 08 ν¨μμ ν΄λ‘μ
νλ‘κ·Έλ¨μ΄ 컀μ§μλ‘ κ΄λ¦¬κ° κ°λ₯ν μμ μ‘°κ°μΌλ‘ λλ μ μλ λ°©λ²μ΄ νμνλ€.
μ€μΉΌλΌμ μ‘΄μ¬νλ μ¬λ¬μ’ λ₯μ ν¨μκ° μ§λ νΉμ§μ μμ보μ.
8.1 λ©μλ
ν¨μλ₯Ό μ μνλ κ°μ₯ νν λ°©λ²μ νΉμ κ°μ²΄μ λ©€λ²λ₯Ό ν¨μλ‘ λ§λλ κ²μ΄λ€.
κ°μ²΄μ λ©€λ²μΈ ν¨μλ₯Ό λ©μλ (method) λΌκ³ νλ€.
8.2 μ§μ ν¨μ
μ€μΉΌλΌλ μλ°μ²λΌ μ μ μν μμ μ μμ ν¨μ νλ‘κ·Έλ¨μΌλ‘ λλμ΄ μ μ°νκ² μ‘°λ¦½ν μ μλ λΉλ© λΈλ‘ (building block) μ μ 곡νλ€.
μλ°λ μ κ·Ό μ μ΄μλ₯Ό ν΅ν λΉκ³΅κ° λ©μλλ₯Ό μ΄μ©νμ§λ§ μ€μΉΌλΌμμλ ν¨μμμ ν¨μλ₯Ό μ μνλ λ°©λ²μΌλ‘ μ μν μ μλ€.
def processFile(filename: String, width: Int) = {
def processLine(filename: String, width: Int, line: String) = {
if (line.length > width)
println(filename + ": " + line.trim)
}
val source = Source.fromFile(filename)
for (line <- source.getLines()) {
processLine(filename, width, line)
}
}
processLine
λ©μλλ processfile
λ΄λΆμμλ§ μ κ·Όν μ μμΌλ©°, μΈλΆμμλ μ κ·Όμ΄ λΆκ°λ₯ νλ€.
8.3 1κΈ κ³μΈ΅ ν¨μ
μ€μΉΌλΌλ 1κΈ κ³μΈ΅ ν¨μ (first class function) λ₯Ό μ 곡νλ€.
ν¨μλ₯Ό μ μνκ³ νΈμΆν λΏλ§ μλλΌ μ΄λ¦μμ΄ λ¦¬ν°λ΄λ‘ νκΈ°ν΄ κ°μ²λΌ μ£Όκ³ λ°μ μ μλ€.
ν¨μ 리ν°λ΄μ μμ€ μ½λμ μ‘΄μ¬νλ λ°λ©΄, ν¨μκ°μ μ€ν μμ μ κ°μ²΄λ‘ μ‘΄μ¬νλ€λ μ μ μλ€.
8.4 κ°λ¨ν ννμ ν¨μ 리ν°λ΄
ν¨μ 리ν°λ΄μ μ’ λ κ°λ¨νκ² λ§λλ λ°©λ²μ μΈμμ νμ μ μ κ±°νλ κ²μ΄λ€.
someNumbers.filter((x) => x > 0)
someNumbers
λΌλ μ μμ 리μ€νΈλ₯Ό κ±Έλ¬λ΄λ νν° ν¨μλ₯Ό μ¬μ©νκΈ° λλ¬Έμ, μ€μΉΌλΌ μ»΄νμΌλ¬λ ν¨μ 리ν°λ΄μ μΈμκ° xκ° μ μλΌλ μ¬μ€μ μλ€.
μ΄λ₯Ό νκ² νμ΄ν (target typing) μ΄λΌκ³ νλλ° ννμμ μ΄λ€ λ°©μμΌλ‘ μ¬μ©νλλμ λ°λΌ μ»΄νμΌλ¬κ° μΆλ‘ νλ νμ μ΄ λ¬λΌμ§κΈ° λλ¬Έμ΄λ€.
8.5 μμΉ νμμ λ¬Έλ²
ν¨μ 리ν°λ΄μ μ’ λ κ°κ²°νκ² λ§λ€κΈ° μν΄ λ°μ€μ νλ μ΄μμ νλΌλ―Έν°μ μμΉ νμμλ‘ μ¬μ©ν μ μλ€.
someNumbers.filter(_ > 0)
λ°μ€μ μ±μλ£μ΄μΌ νλ λΉμΉΈμΌλ‘ μκ°ν΄λ μ’λ€.
λλ‘λ λ°μ€μ μΈμμ μμΉ νμμλ‘ μ¬μ©ν λ μ»΄νμΌλ¬κ° μΈμμ νμ μ 보λ₯Ό μ°Ύμ§ λͺ»ν κ²½μ°κ° μλ€.
μ΄λ΄ κ²½μ°μλ μ½λ‘ μ μ΄μ©νμ¬ νμ μ λͺ μν΄μ£Όλ©΄ λλ€.
val f = (_: Int) + (_: Int)
8.6 λΆλΆ μ μ© ν¨μ
μ 체 νλΌλ―Έν° λͺ©λ‘μ λ°μ€λ‘ λ°κΏμλ μλ€.
μλ₯Ό λ€λ©΄ println(_)
μ΄λΌκ³ μ°μ§ μκ³ println _
μ΄λΌκ³ μΈ μ μλ€.
def sum(a: Int, b: Int, c: Int) = a + b + c
val a = sum _
a(1, 2, 3)
// 6
μ μ½λλ μ€μΉΌλΌ μ»΄νμΌλ¬κ° λΆλΆ μ μ© ν¨μ ννμ sum _
μμ λΉ μ§ μΈμ 3κ°λ₯Ό λ°λ ν¨μ«κ°μ μΈμ€ν΄μ€ν νλ€.
μ€μΉΌλΌ μ»΄νμΌλ¬λ a(1, 2, 3)
μ ν¨μ«κ°μ apply λ©μλμ λν νΈμΆλ‘ ν΄μν΄ 1, 2, 3μ μ λ¬νλ€.
λ°λΌμ a(1, 2, 3)
μ a.apply(1, 2, 3)
μ μ§§κ² μ΄ κ²μ΄λ€.
λ€μκ³Ό κ°μ΄ νμν μΈμμ€ μΌλΆλ§ λ겨μ λΆλΆ μ μ© ν¨μλ₯Ό λ§λ€ μλ μλ€.
val b = sum(1, _:Int, 3)
b(2)
// 6
μλλ 리ν°λ΄ ν μ€νΈμ κ°μ²΄ ν μ€νΈ νμ κ²½μ° κ²°κ³Όμ΄λ€.
def makeIncreaser(more: Foo) = (x: Int) => x + more.f
var value = 1
val increaser = makeIncreaser(value)
value = 2
println(increaser(3))
// 4
case class Foo(var f: Int)
def makeIncreaser(more: Foo) = (x: Int) => x + more.f
val foo = Foo(1)
val increaser = makeIncreaser(foo)
foo.f = 2
println(increaser(3))
// 5
8.7 ν΄λ‘μ
μ£Όμ΄μ§ ν¨μ 리ν°λ΄λΆν° μ€ν μμ μ λ§λ€μ΄λΈ κ°μ²΄μΈ ν¨μ«κ° (κ°μ²΄) μ ν΄λ‘μ (closure) λΌκ³ νλ€.
μλ°μ€ν¬λ¦½νΈμ ν΄λ‘μ μ λΉμ·ν κ²μΌλ‘ νλ¨.
8.8 νΉλ³ν ννμ ν¨μ νΈμΆ
λ°λ³΅ νλΌλ―Έν°
λ°λ³΅ κ°λ₯ν μΈμλ₯Ό νκΈ°νλ €λ©΄ λ³ν (*) λ₯Ό μΈμμ νμ λ€μμ μΆκ°νλ©΄ λλ€.
def echo(args: String*) =
for (arg <- args) println(arg)
echo()
echo("one")
echo("hello", "world")
λ°°μ΄μ λ°λ³΅ μΈμλ‘ μ λ¬νκΈ° μν΄ λ€μκ³Ό κ°μ΄ μ½λ‘ (π μ _*
κΈ°νΈλ₯Ό μΆκ°ν΄μΌ νλ€.
aka. κ°λ³μΈμ
μ΄λ¦ λΆμΈ μΈμ
μ΄λ¦ λΆμΈ μΈμλ₯Ό μ΄μ©ν΄ νΈμΆνλ©΄ μΈμλ€μ μμλ₯Ό λ°κΎΈμ΄ μ λ¬ν΄λ νΈμΆμ μλ―Έκ° λ³νμ§ μλλ€.
def speed(distance: Float, time: Float): Float =
distance / time
speed(distance = 100, time = 10)
or
speed(time = 10, distance = 100)
λν΄νΈ μΈμ£κ°
μ€μΉΌλΌμμ νλΌλ―Έν°μ λν΄νΈκ°μ μ§μ ν μ μλ€.
def printTime(
out: java.io.PrintStream = Console.out,
divisor: Int = 1
) =
outprintln("time = " + System.currentTimeMillis() / divisor)
νΉμ νλΌλ―Έν°λ₯Ό λͺ μνκ³ μΆμΌλ©΄ λ€μκ³Ό κ°μ΄ νΈμΆνλ€.
printTime(divisor = 1000)
8.9 꼬리 μ¬κ·
λ§μ§λ§μ μμ μ μ¬κ· νΈμΆνλ κ²½μ°λ₯Ό 꼬리μ¬κ· (tail recursive) λΌκ³ νλ€.
λ¬Έμ λ₯Ό ν΄κ²°ν λ μ¬κ·λ₯Ό μ¬μ©νλ κ²μ λλ €μνμ§ μμλ λλ€. μ¬κ·λ₯Ό μ¬μ©νλ ν΄λ²μ΄ 루νλ₯Ό μ¬μ©νλ ν΄λ²λ³΄λ€ κ°κ²°νκ³ μ°μν κ²½μ°κ° μ’ μ’ μλ€.
꼬리 μ¬κ· ν¨μ μΆμ
꼬리 μ¬κ· ν¨μλ μ¬κ· νΈμΆλ§λ€ μλ‘μ΄ μ€νμ λ§λ€μ§ μκ³ κ°μ μ€ν νλ μμ μ¬νμ© νλ€.
def boom(x: Int): Int =
if (x == 0) throw new Exception("boom!")
else boom(x - 1) + 1
μ μ½λμ boom
ν¨μλ μ¬κ· νΈμΆ νμ λνκΈ° μ°μ°μ μννκΈ° λλ¬Έμ 꼬리 μ¬κ·κ° μλλ€.
μ€ννλ©΄ λ€μκ²°κ³Όλ₯Ό λ³Ό μ μλ€.
boom(3)
java.lang.Exception: boom!
at .boom(<console>:5)
at .boom(<console>:6)
at .boom(<console>:6)
at .boom(<console>:6)
at .<init>(<console>:6)
...
boom μ μμ ν΄ κΌ¬λ¦¬ μ¬κ·λ‘ λ§λ€λ©΄ λ€μκ³Ό κ°λ€.
def bang(x: Int): Int =
if (x == 0) throw new Exception("bang!")
else bang(x - 1)
bang(5)
java.lang.Exception: bang!
at .bang(<console>:5)
at .<init>(<console>:6)...
μ΄λ²μλ bang
μ λ¨ νλμ μ€νλ§ λ³΄μΈλ€.
꼬리 μ¬κ·μ νκ³
JVM λͺ λ Ήμ΄ μ§ν©λ§μΌλ‘λ κ³ μμ€μ 꼬리 μ¬κ·λ₯Ό ꡬννκΈ°μ μ΄λ €μμ΄ μκΈ° λλ¬Έμ, μ€μΉΌλΌμ 꼬리 μ¬κ· μ΅μ νμλ νκ³κ° μλ€.
κΌ¬λ§ μ¬κ· μ΅μ νλ λ©μλλ μ€μ²© ν¨μκ° λ§μ§λ§ μ°μ°μΌλ‘μ μμ μ μ§μ νΈμΆνλ κ²½μ°μλ§ μ΄λ€μ§λ€.
8.10 κ²°λ‘
μ€μΉΌλΌμ ν¨μλ₯Ό μμ보μλ€.
μ€μΉΌλΌλ λ©μλ μ΄μΈμλ μ§μν¨μ, ν¨μ 리ν°λ΄, ν¨μ«κ°μ μ 곡νλ©° μΌλ°μ μΈ ν¨μ νΈμΆ μΈμ, λΆλΆ μ μ© ν¨μμ λ°λ³΅ μΈμλ±μ μ¬μ©ν μ μλ€.
λ€μμ₯μμλ ν¨μμ μ§μμ ν΅ν νλ¦μ μ΄λ₯Ό μμ보μ.
Chapter 09 νλ¦ μ μ΄ μΆμν
μ€μΉΌλΌμλ λ΄μ₯ μ μ΄ μΆμνκ° λ§μ§ μλ€.
νμ§λ§ μμ μ κ³ μ ν μ μ΄ μΆμνλ₯Ό μμ±ν μ μλ€.
9.1 μ½λ μ€λ³΅ μ€μ΄κΈ°
ν¨μλ₯Ό μΈμλ‘ λ°λ ν¨μλ₯Ό κ³ μ°¨ ν¨μ (higher-order function) μ΄λΌκ³ νλλ° μ΄λ₯Ό μ΄μ©νμ¬ μ½λλ₯Ό λ κ°λ¨νκ² μμΆν μ μλ κΈ°νλ₯Ό μ 곡νλ€.
κ³ μ°¨ ν¨μλ₯Ό μ¬μ©ν λμ μ₯μ μ€ νλλ μμ λ§μ μΆμνν νλ¦ μ μ΄λ₯Ό μμ±ν μ μμ΄ μ½λμ μ€λ³΅μ μ€μΌ μ μλ€λ μ μ΄λ€.
object FileMatcher {
private def filesHere = (new java.io.File(".")).listFiles
private def filesMatching(matcher: String => Boolean) =
for (file <- filesHere; if matcher(file.getName))
yield file
def fileEnding(query: String) =
filesMatching(_.endsWith(query))
def filesContaining(query: String) =
filesMatching(_.contains(query))
def filesRegex(query: String) =
filesMatching(_.matches(query))
}
9.2 ν΄λΌμ΄μΈνΈ μ½λ λ¨μνκ² λ§λ€κΈ°
def containsOdd(nums: List[Int]) = nums.exists(_ % 2 == 1)
μ μ½λμ κ°μ΄ exists
μ κ°μ 루ν λ©μλλ₯Ό μ¬μ©νλ©΄ μ½λλ₯Ό λ λ¨μνκ² λ§λ€μ μλ€.
9.3 컀λ§
def curriedSum(x: Int)(y: Int) = x + y
curriedSum(1)(2)
// 3
μμ κ°μ΄ ν¨μλ₯Ό μ°μμ μΌλ‘ νΈμΆνμ¬ νΈμΆ κ°λ₯ν κ°μ λ°ννλ κ²μ΄λ€.
9.4 μλ‘μ΄ μ μ΄ κ΅¬μ‘° μμ±
μ΄μ try ~ catch ~ finally
ꡬ문μμ μ¬μ©νλ λ°©μμ μλ‘μ΄ μ μ΄κ΅¬μ‘°λ‘ λ³κ²½νμ¬ λ€μκ³Ό κ°μ΄ νννλ€.
def widthPrintWriter(file: File, op: PrintWriter => Unit) = {
val writer = new PrintWriter(file)
try {
op(writer)
} finally {
writer.close()
}
}
withPrintWriter(
new File("date.txt"),
writer => writer.println(new java.util.Date)
)
μ λ©μλλ₯Ό μ¬μ©νλ κ²½μ° withPrintWriter
κ° νμΌ λ«κΈ°λ₯Ό 보μ₯νλ€λ μ₯μ μ΄ μλ€.
μ μ΄ μΆμνλ₯Ό νλ ν¨μκ° μμμΌ μ΄μ΄ νΉμ ν¨μμκ² ν΄λΉ μμμ λΉλ €μ£ΌκΈ° λλ¬Έμ΄λ€.
λ€μμ 컀λ§μ μ΄μ©ν λΉλ €μ£ΌκΈ° λ°©μμ μ΄μ©ν νμΌμ°κΈ° μ΄λ€.
def withPrintWriter(file: File)(op: PrintWriter => Unit) = {
val writer = new PrintWriter(file)
try {
op(writer)
} finally {
writer.close()
}
}
val file = new File("date.txt")
withPrintWriter(file) {
writer => writer.println(new java.util.Date)
}
File μΈμλ₯Ό ν¬ν¨νλ 첫 μΈμ λͺ©λ‘μ μκ΄νΈλ‘ κ°μλ€.
ν¨μ μΈμλ₯Ό ν¬ν¨νλ λ λ²μ§Έ μΈμ λͺ©λ‘μλ μ€κ΄νΈλ₯Ό μ¬μ©νλ€.
9.5 μ΄λ¦μ μν νΈμΆ νλΌλ―Έν°
def byNameAssert(predicate: => Boolean) =
if (assertionsEnabled && !predicate)
throw new AssertionError
def boolAssert(predicate: Boolean) =
if (assertionsEnabled && !predicate)
throw new AssertionError
byNameAssert(5 > 3)
boolAssert(5 > 3)
byNameAssert
κ³Ό boolAssert
μ κ²°κ³Όλ μ¬μ©νλ μ½λλ κ°λ€.
μ λμ κ°μ₯ μ€μν μ°¨μ΄μ μ boolAssert
μΈμ νμ
μ΄ Boolean
μ΄λ―λ‘, boolAssert(5 > 3)
μ κ΄νΈ μμ μμΉν ννμμ boolAssert
νΈμΆ μ§μ μ κ³μ°νλ€.
λ§μ½ boolAssert
μΈμνμ
μ΄ x / 0 == 0
μ΄λΌλ©΄ boolAssert
μ μΈμμ ννμμ κ³μ°ν¨μ λ°λΌ μλ¬κ° λ°μλλ€.
νμ§λ§ κ°μ μ½λμ byNameAssert
λ μμΈκ° λ°μνμ§ μλλ€.
9.6 κ²°λ‘
μ€μΉΌλΌ λΌμ΄λΈλ¬λ¦¬μ κ³ μ°¨ν¨μ, μ»€λ§ λ±μ μ΄μ©νμ¬ μ’ λ κ°κ²°ν λ¬Έλ²μΌλ‘ νμ©νλ λ°©λ²μ μμ보μλ€.
Chapter 10 μμκ³Ό ꡬμ±
ν΄λμ€ κ°μ κ·Όλ³Έμ μΈ λ κ°μ§ κ΄κ³μΈ μμ (inheritance) κ³Ό κ΅¬μ± (composition) μ λΉκ΅ν κ²μ΄λ€.
10.1 2μ°¨μ λ μ΄μμ λΌμ΄λΈλ¬λ¦¬
쑰립μ λ΄λΉνλ above μ beside λ μ μ ν κ²μ΄λ€.
elem(s: String) = Element
val column1 = elem("hello") above elem("***")
val column2 = elem("***") above elem("world")
hello***
***world
쑰립 μ°μ°μλ νΉμ λλ©μΈμ μμλ₯Ό κ²°ν©νμ¬ μλ‘μ΄ μμλ₯Ό λ§λ€μ΄λ΄κΈ° λλ¬Έμ μ½€λΉλ€μ΄ν° (combinator) λΌκ³ λΆλ₯Έλ€.
10.2 μΆμ ν΄λμ€
abstract
ν€μλλ‘ μλμ κ°μ΄ ν΄λμ€λ₯Ό μ μ λ΄λ¦°λ€.
abstract class Element {
def contents: Array[String]
}
contents
λ Element
ν΄λμ€μ μΆμ λ©€λ² (abstract member) μ΄λ€.
abstract
μμμλ ν΄λΉ ν΄λμ€ μμ ꡬνμ΄ μλ μΆμ λ©€λ²κ° μμμ μλ €μ€λ€. λλ¬Έμ μΆμν΄λμ€λ‘λ μΈμ€ν΄μ€λ₯Ό λ§λ€μ μλ€.
λ§μ½ λ©μλμ ꡬνμ΄ μλ€λ©΄ ꡬ체 λ©μλ (concrete method) λΌκ³ νλ€.
10.3 νλΌλ―Έν° μλ λ©μλ μ μ
νλλ λ©μλμ€ μ΄λ€ λ°©μμΌλ‘ μμ±μ μ μ νλλΌλ ν΄λΌμ΄μΈνΈ μ½λμλ μν₯μ λΌμΉμ§ λ§μμΌ νλ€λ λ¨μΌ μ κ·Ό μμΉ (uniform assess principle) μ λΆν©νλ€.
"hello".length // λΆμν¨κ³Όκ° μμΌλ―λ‘ () λ₯Ό μ¬μ©νμ§ μμ
println() // () μ μ¬μ©νλ νΈμ΄ λμ
νΈμΆ νλ ν¨μκ° μ΄λ ν μμ μ μννλ€λ©΄ λΉ κ΄νΈλ₯Ό μ¬μ©νλΌ
νμ§λ§ νλ‘νΌν°μ λν μ κ·Όλ§μ μννλ€λ©΄ κ΄νΈλ₯Ό λΌλ²λ €λΌ.
10.4 ν΄λμ€ νμ₯
μΆμν΄λμ€λ₯Ό νμ₯νλ €λ©΄ extends
ν€μλλ₯Ό μ¬μ©νμ¬ μ μνλ€.
class ArrayElement(conts: Array[String]) extends Element {
def contents: Array[String] = conts
}
extends
μ μ λ€μ ν¨κ³Όλ₯Ό κ°μ§λ€.
- νμ₯ ν΄λμ€λ μΆμν΄λμ€μμ λΉκ³΅κ° (private) κ° μλ λ©€λ²λ₯Ό λͺ¨λ λ¬Όλ €λ°λλ€.
- νμ₯ ν΄λμ€λ₯Ό μΆμν΄λμ€μ μλΈνμ (subtype) μΌλ‘ λ§λ λ€.
νμ₯ ν΄λμ€ (μλΈ ν΄λμ€) -> μΆμ ν΄λμ€ (μνΌ ν΄λμ€)
10.5 λ©μλμ νλ μ€λ²λΌμ΄λ
μ€μΉΌλΌμμλ νλμ λ©μλκ° κ°μ λ€μμ€νμ΄μ€μ μνλ€.
class CompilesFine {
private int f = 0;
public int f() {
return 1;
}
}
μ μλ° μ½λλ λ¬Έμ μμ΄ μ»΄νμΌ ν μ μμ§λ§ μλ μ€μΉΌλΌ μ½λλ νλμ λ©μλκ° κ°μ μ΄λ¦μΌλ‘ μ»΄νμΌ ν μ μλ€.
class WontCompile {
private var f = 0
def f = 1
}
μλ°μλ 4κ°μ λ€μμ€νμ΄μ€ (νλ, λ©μλ, νμ
, ν¨ν€μ§) κ° μμ§λ§
μ€μΉΌλΌμλ 2κ°μ λ€μμ€νμ΄μ€ (κ°, νμ
) λ§ μλ€.
10.6 νλΌλ―Έν° νλ μ μ
class Cat {
val dangerous = false
}
class Tiger (
override val dangerous: Boolean,
private var age: Int
) extends Cat
μλ λ λ©€λ²λ κ°κ° λμνλ μΈμλ‘ μ΄κΈ°ν λλ€.
μΈμμ μ΄λ¦μ μμλ‘ param1
, param2
λΌκ³ λΆμλ€.
class Tiger(param1: Boolean, param: Int) extends Cat {
override val dangerous = param1
private var age = param2
}
μ€μν κ²μ μΈμμ μ΄λ¦μ΄ μ€μ½νμ μλ λ€λ₯Έ μ΄λ¦κ³Ό μΆ©λνμ§ μμμΌ νλ€λ κ²μ΄λ€.
10.7 μνΌ ν΄λμ€ μμ±μ νΈμΆ
class LineElements(s: String) extends ArrayElement(Array(s)) {
override def width = s.length
override def height = 1
}
LineElement
ν΄λμ€λ Array(s)
λ₯Ό ArrayElement
λ€μ΄ κ΄νΈλ‘ λ¬Άμ΄ νκΈ°ν¨μΌλ‘μ¨ ArrayElement
μ μ£Ό μμ±μμ μ λ¬νλ€.
10.8 override μμμ μ¬μ©
μ€μΉΌλΌμμλ λΆλͺ¨ ν΄λμ€μ μλ ꡬ체 (concrete) λ©€λ²λ₯Ό μ€λ²λΌμ΄λ νλ λͺ¨λ λ©€λ²μ override
μμμλ₯Ό λΆμ¬μΌ νλ€.
10.9 λ€νμ±κ³Ό λμ λ°μΈλ©
μμ ν΄λμ€λ₯Ό μμ λ°λ ν΄λμ€κ° μ¬λ¬ νμ μ κ°μ²΄λ₯Ό μ°Έμ‘°ν μ μμμ λ€νμ± (polymorphism) μ΄λΌκ³ νλ€.
λ³μλ ννμμ λν λ©μλ νΈμΆμ λμ μΌλ‘ λ°μΈλ© νλ€λ μ μ΄λ€.
μ΄λ μ€νμμ μ μ€μ λ‘ κ·Έ κ°μ²΄κ° μ΄λ€ νμ μΈκ°λ₯Ό λ°λ₯Έλ€λ λ»μ΄λ€.
10.10 final λ©€λ² μ μΈ
μμ ν΄λμ€κ° μ€λ²λΌμ΄λ νμ§ λͺ»νκ² λ§κ³ μΆμλ μ¬μ©
class ArrayElement extends Element {
final override def demo() = {
println("ArrayElement's implementation invoked")
}
}
10.11 μμκ³Ό κ΅¬μ± μ¬μ©
ꡬμ±κ³Ό μμμ μ΄λ―Έ μ‘΄μ¬νλ ν΄λμ€λ₯Ό μ΄μ©ν΄ μλ‘μ΄ ν΄λμ€λ₯Ό μ μνλ λ κ°μ§ λ°©λ²μ΄λ€.
10.12 above, beside, toString ꡬν
abstract class Element {
def contents: Array[String]
def width: Int =
if (height == 0) 0 else contents(0).length
def height: Int = content.length
def above(that: Element): Element =
new ArrayElement(this.contents ++ that.contents)
def beside(that: Element): Element =
new ArrayElement(
for (
(line1, line2) <- this.contnets zip that.contnets
) yield line + line2
)
override def toString = contents mkString "\n"
}
10.13 ν©ν 리 κ°μ²΄ μ μ
ν©ν 리 κ°μ²΄λ λ€λ₯Έ κ°μ²΄λ₯Ό μμ±νλ λ©μλλ₯Ό μ 곡νλ κ°μ²΄λ€.
new
λ₯Ό μ΄μ©νμ¬ μ§μ κ°μ²΄λ₯Ό λ§λ€κΈ° 보λ€λ ν©ν 리 λ©μλλ‘ κ°μ²΄λ₯Ό μμ±νλ€.
ν©ν 리 λ©μλλ₯Ό μμ±νλ μ΄μ μ μμ± κΈ°λ₯μ νκ³³μ λͺ¨μ μ 곡νκ³ κ΅¬μ²΄μ μΈ λ΄λΆ ννμ κ°μΆμ μλ€λ μ μ΄λ€.
μ΄λ κ² μΈλΆμ¬νμ μ¨κΈ°λ©΄ ν΄λΌμ΄μΈνΈλ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ’ λ μ½κ² μ΄ν΄ κ°λ₯νκ³ , λμ€μ ν΄λΌμ΄μΈνΈμ μ½λλ₯Ό κΉ¨μ§ μκ³ κ΅¬νμ λ³κ²½νκΈ°μλ μ 리νλ€.
object Element {
def elem(contents: Array[String]): Element =
new ArrayElement(contents)
def elem(chr: Char, width: Int, height: Int): Element =
new UniformElement(chr, width, height)
def elem(line: String): Element =
new LineElement(line)
}
10.14 λμ΄μ λλΉ μ‘°μ
μμ μ½λ μ€λͺ
10.15 νλ° λͺ¨μ μνν΄λ³΄κΈ°
import Element.elem
object Spiral {
val space = elem(" ")
val corner = elem("+")
def spiral(nEdges: Int, direction: Int): Element = {
if (nEdges == 1)
elem("+")
else {
val sp = spiral(nEdges - 1, (direction + 3) % 4)
def verticalBar = elem('|', 1, sp.height)
def horizontalBar = elem('-', sp.width, 1)
if (direction == 0)
(corner beside horizontalBar) above (sp beside space)
else if (direction == 1)
(sp above space) beside (corner above verticalBar)
else if (direction == 2)
(space beside sp) above (horizontalBar beside corner)
else
(verticalBar above corner) beside (space above sp)
}
}
def main(args: Array[String]) = {
val nSides = args(0).toInt
println(spiral(nSides, 0))
}
}
10.16 κ²°λ‘
κ°μ²΄ μ§ν₯μ λ§μ κ°λ μ μ΄ν΄λ³΄μλ€.