153
3
장
기초를 튼튼히
연산자 연산 설명
<
보다 작다 왼쪽 항의 값이 오른쪽 항의 값보다 작다.
<
=
보다 작거나 같다 왼쪽 항의 값이 오른쪽 항의 값보다 작거나 같다.
==
같다 왼쪽 항의 값과 오른쪽 항의 값이 같다.
!
=
같지 않다 왼쪽 항의 값과 오른쪽 항의 값이 같지 않다.
&&
와
||
연산은 ‘쇼트서킷
short
-
circuiting
’ 연산자다. 이들은 답을 알게 되면 더 이상 인자 계산을 하
지 않는다.
대부분의 연산자는 자바나 다른 언어와 마찬가지로 작동한다. 예외는
==
와 그 연산의 부정인
!
=
이다. 자바에서
==
는 객체 참조만 비교하며, 필드값을 비교하는 등의 논리적 동등성 검사를
수행하지 않는다. 논리적 동등성 검사를 위해서는
equals
메서드를 사용해야 한다. 따라서 타
입이 같은 두 개의 다른 객체가 필드값이 같은 경우 (즉, 상태가 동일함 ), 자바에서는
==
가 여전
히
false
를 반환할 것이다.
반면 스칼라는
==
를 논리적 동등성에 사용하되,
equals
메서드를 호출한다. 논리적 동등성을
검사하지 않고 참조를 비교하고 싶은 경우를 위해 새로운 메서드인
eq
를 제공한다 (
10
.
6
절 ‘객
체의 동등성’에서 객체 동등성에 대해 자세히 다룰 것이다).
3.9
try
,
catch
,
finally
사용하기
함수형 구성 요소와 강력한 타입판정을 통해 스칼라는 예외나 예외 처리의 필요성을 줄이는 코
딩 유형을 장려한다. 그럼에도 불구하고 여전히 예외를 사용한다. 특히 예외를 더 흔하게 사용하
는 자바 코드와 상호 작용하는 경우에는 더 그렇다.
NOTE
_
자바와 달리 스칼라에는 검증 예외
checked
exception
가 없다. 이제 검증 예외는 성공적이지 않은 설계
로 간주되기 때문이다. 자바의 검증 예외는 스칼라에서는 비검증으로 취급된다. 또한 스칼라 메서드 정의에는
throws
절이 없다. 대신 자바와의 상호 운용에 유용한 @
throws
(
http
://
bit
.
ly
/
1rGL04n
) 애노테이션이 있다.
23
.
2
절 ‘애노테이션’을 참조하라.
154
1
부
스칼라와의 만남
스칼라는 다른 패턴 매치와 마찬가지로 예외 처리를 취급한다. 따라서 여러 종류의 예외를 간
결하게 처리하도록 구현할 수 있다.
이런 특징이 일반적인 애플리케이션 시나리오에서 실제 쓰이는 모습을 살펴보자. 파일을 열고
어떤 방식으로 처리하고자 한다. 여기서는 그냥 라인 수를 셀 것이다. 하지만 몇 가지 예외적인
시나리오를 처리해야 한다. 사용자가 지정한 파일이 없을 수도 있다. 또는 파일을 처리하는 도
중에 무언가 잘못될 수도 있다 (어떤 일이 일어나는지 알아보기 위해 임의로 잘못된 경우를 만
들어낼 것이다 ). 프로그램에서 열어둔 모든 파일 핸들은 성공적으로 처리했는지와 관계없이
닫도록 보장해야 한다.
//
src
/
main
/
scala
/
progscala2
/
rounding
/
TryCatch
.
scala
package progscala2
.
rounding
object TryCatch
{
/**
사용법
:
scala rounding
.
TryCatch filename1 filename2
...
*/
def main
(
args
:
Array
[
String
])
=
{
args foreach
(
arg
=
>
countLines
(
arg
))
//
➊
}
import scala
.
io
.
Source
//
➋
import scala
.
util
.
control
.
NonFatal
def countLines
(
fileName
:
String
)
=
{
//
➌
println
()
//
읽기
쉽게
하기
위해
빈
줄을
넣는다
.
var source
:
Option
[
Source
]
=
None
//
➍
try
{
//
➎
source
=
Some
(
Source
.
fromFile
(
fileName
))
//
➏
val size
=
source
.
get
.
getLines
.
size
println
(
s
"
file
$
fileName has
$
size lines
")
}
catch
{
case NonFatal
(
ex
)
=
>
println
(
s
"
Non fatal exception
!
$
ex
")
//
➐
}
finally
{
for
(
s
<
-
source
)
{
//
➑
println
(
s
"
Closing
$
fileName
...")
s
.
close
}
}
}
}
155
3
장
기초를 튼튼히
➊
foreach
를 사용해서 인자 목록에 대해 루프를 돌면서 각 인자를 처리한다. 루프를 매번 돌
때 그리고 마지막 식인
foreach
의 결과로
Unit
이 반환된다.
➋ 입력을 읽기 위해
scala
.
io
.
Source
(
http
://
bit
.
ly
/
1toCEnE
)를 임포트하고, ‘치명적이지
않은’ 오류에 대해 매치시키기 위해
scala
.
util
.
control
.
NonFatal
(
http
://
bit
.
ly
/
1tI2D9y
)
을 임포트한다.
➌ 각 파일 이름에 대해 라인 수를 센다.
➍
source
를
Option
으로 정의해서 실제 인스턴스가 있는지 여부를
finally
절에서 알 수 있게
한다.
➎
try
절을 시작한다.
➏
Source
.
fromFile
은 파일이 없으면
java
.
io
.
FileNotFoundException
(
http
://
bit
.
ly
/
1G2Hr34
)을 던진다. 그렇지 않으면 돌려받은
Source
인스턴스를
Some
으로 감싼다. 다음 줄
에서
get
을 호출해도 안전하다. 여기까지 진행했다면 예외가 발생하지 않아서
Some
이라는 것
이 확실하기 때문이다.
➐ 치명적이지 않은 오류를 잡아낸다. 예를 들어 메모리 부족
out
of
memory
오류는 치명적인 오류다.
➑
for
내장을 사용해서
Some
에서
Source
인스턴스를 뽑아내고 닫는다.
source
가
None
이라면
아무 일도 일어나지 않는다!
catch
절을 보라. 스칼라는 잡아내고 싶은 예외를 선택하기 위해 패턴 매치를 사용한다. 이는
자바에서 각 예외에 대해
catch
절을 따로 두는 것보다 훨씬 더 유연하고 간결하다. 여기서
case
NonFatal
(
ex
) =
>
...
는
scala
.
util
.
control
.
NonFatal
을 사용해서 치명적이지 않은 모든
오류와 일치시킨다.
finally
절을 사용해서 한 곳에서 자원을 적절히 정리했다.
finally
가 없다면, 파일 핸들을 제
대로 닫는 것을 보장하기 위해
try
와
catch
의 끝에 같은 논리를 반복해야 할 것이다. 여기서
for
내장을 사용해서
Option
에서
Source
를 뽑아냈다. 옵션이 실제로
None
이라면 아무 일도 벌어지
지 않는다. 즉,
close
호출이 있는 블록이 실행되지 않는다.
TIP
이런 표현은 널리 쓰이는 관용구다.
Option
을 검사해서
Some
이면 어떤 작업을 수행하고,
None
이면 무시할
필요가 있을 때는
for
내장을 사용하라.
Get 프로그래밍 스칼라: 실용적인 스칼라 활용법을 익히는 가장 확실한 실전 바이블 (2.11.x 버전 기반) now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.