440
2
부
기본기 다지기
라 할 수 있다.
SQL
이나
NoSQL
데이터 집합에
22
개 이상의 필드가 들어 있는 경우는 흔하다.
튜플은 작은 스키마의 경우 필드(컬럼)의 순서와 타입을 유지해주기 때문에 유용하다. 하지만
22
개라는 제한은 문제다.
스칼라
2
.
10
의 케이스 클래스도 필드 수가
22
개로 제한된다. 하지만 케이스 클래스에 대한 이
런 구현상 제약이 스칼라
2
.
11
에서는 사라졌다. 따라서 데이터 애플리케이션에서는 필드가
22
개를 넘어서는 레코드에 대해 케이스 클래스를 사용할 수 있다.
NOTE
_
스칼라
2
.
1
0
이나 그 이전 버전에서는 케이스 클래스에 필드를 최대
22
개까지 선언할 수 있었다. 하
지만 스칼라
2
.
11
에서는 이런 제약이 사라졌다.
바라건대 튜플이나 프로덕트에 대한
22
원소 제약도 스칼라의 향후 버전에서는 사라졌으면 한다.
10.5
Predef
객체
여러분의 편의를 위해, 코드를 컴파일할 때마다 스칼라 컴파일러는
java
.
lang
패키지의 정의
를 임포트할 뿐만 아니라(이는
javac
와 같다 ) 자동으로 최상위 스칼라 패키지인
scala
의 정
의를 임포트한다. 따라서 자바와 스칼라에서 일반적인 여러 타입은 특별히 임포트하거나 전체
경로명으로 사용하지 않아도 된다. 추가로 컴파일러는 수많은 유용한 정의를 제공하는
Predef
(
http
://
bit
.
ly
/
1086O2z
) 객체에 있는 정의도 임포트한다. 그중 상당한 양을 이전에 이미 설
명했다.
이제
Predef
가 제공하는 특징을 하나하나 살펴보자. 스칼라
2
.
11
의
Predef
에 많은 변화가 있
었다. 그중 상당수는 눈에 띄지는 않는다. 우리는
2
.
11
버전을 설명할 것이다.
10.5.1
암시적 변환
먼저
Predef
는 수많은 암시적 변환을 제공한다. 그런 변환 중 한 가지는
AnyVal
타입을 둘러싸
는 래퍼다.
441
10
장
스칼라 객체 시스템 I
@
inline implicit def byteWrapper
(
x
:
Byte
)
=
new runtime
.
RichByte
(
x
)
@
inline implicit def shortWrapper
(
x
:
Short
)
=
new runtime
.
RichShort
(
x
)
@
inline implicit def intWrapper
(
x
:
Int
)
=
new runtime
.
RichInt
(
x
)
@
inline implicit def charWrapper
(
c
:
Char
)
=
new runtime
.
RichChar
(
c
)
@
inline implicit def longWrapper
(
x
:
Long
)
=
new runtime
.
RichLong
(
x
)
@
inline implicit def floatWrapper
(
x
:
Float
)
=
new runtime
.
RichFloat
(
x
)
@
inline implicit def doubleWrapper
(
x
:
Double
)
=
new runtime
.
RichDouble
(
x
)
@
inline implicit def booleanWrapper
(
x
:
Boolean
)
=
new runtime
.
RichBoolean
(
x
)
Rich
*
타입은
<
=
나
compare
같은 비교 메서드를 포함한 여러 추가 메서드를 제공한다.
@
inline
애노테이션은 컴파일러에 이 메서드 호출을 ‘인라인
inline
’하라고, 즉
new
runtime
.
RichY
(
x
)
를
직접 집어넣어서 함수 호출 횟수를 줄이라고 알려준다.
바이트에 대한 타입이 따로 있어야 하는 이유는 뭘까? 왜 모든 메서드를
Byte
자체에 넣지 않은
걸까? 바이트 코드의 구현 요구 사항으로 인해, 추가 메서드를
Byte
에 넣으면 인스턴스가 힙에
할당되기 때문이다. 다른
AnyVal
인스턴스와 마찬가지로
Byte
의 인스턴스도 실제로는 힙에 할
당되지 않는 대신 자바의
byte
기본 타입으로 표현된다. 따라서 별도의
Rich
*
타입을 두는 것은
실제 추가 메서드가 필요한 때가 아닌 경우의 힙 할당을 방지해준다.
자바의 변경 가능 배열을
scala
.
collection
.
mutable
.
WrappedArray
(
http
://
bit
.
ly
/
10FtpV6
)로 감싸주는 메서드도 있다. 배열에 컬렉션 메서드를 추가해주는
WrappedArray
에
대해서는 이미
6
장에서 설명했다.
implicit def wrapIntArray
(
xs
:
Array
[
Int
]):
WrappedArray
[
Int
]
implicit def wrapDoubleArray
(
xs
:
Array
[
Double
]):
WrappedArray
[
Double
]
implicit def wrapLongArray
(
xs
:
Array
[
Long
]):
WrappedArray
[
Long
]
implicit def wrapFloatArray
(
xs
:
Array
[
Float
]):
WrappedArray
[
Float
]
implicit def wrapCharArray
(
xs
:
Array
[
Char
]):
WrappedArray
[
Char
]
implicit def wrapByteArray
(
xs
:
Array
[
Byte
]):
WrappedArray
[
Byte
]
implicit def wrapShortArray
(
xs
:
Array
[
Short
]):
WrappedArray
[
Short
]
implicit def wrapBooleanArray
(
xs
:
Array
[
Boolean
]):
WrappedArray
[
Boolean
]
implicit def wrapUnitArray
(
xs
:
Array
[
Unit
]):
WrappedArray
[
Unit
]
왜 각
AnyVal
타입마다 별도의 메서드를 제공하는 걸까? 각각은 자바에서 기본 타입에 대한 배
열이 박스에 넣은 원소의 배열보다 더 효율적이라는 사실을 활용하기 위해
WrappedArray
의 서
442
2
부
기본기 다지기
브클래스를 사용한다. 그러므로 덜 효율적인 참조 타입에 대한 일반적인 배열의 사용을 피할 수
있다.
scala
.
collection
.
mutable
.
ArrayOps
(
http
://
bit
.
ly
/
1pbp9HU
)로 변환하는 비슷한 메서
드도 있다.
WrappedArray
와
ArrayOps
의 유일한 차이는
WrappedArray
가 제공하는
filter
와
같은 변환 함수가 새로운
WrappedArray
를 반환하는 반면
ArrayOps
에 있는 변환 함수는
Array
를 반환한다는 점에 있다.
WrappedArray
나
ArrayOps
와 마찬가지로
String
에 대한 암시적 변환인
scala
.
collection
.
immutable
.
WrappedString
(
http
://
bit
.
ly
/
1wO5q1G
)과
scala
.
collection
.
immutable
.
StringOps
(
http
://
bit
.
ly
/
1bvlHxv
)도 있다. 이 둘도
String
에 대한 컬렉션 메서드를 제공하
며,
String
을
Char
의 컬렉션처럼 다룰 수 있게 해준다. 이를 위해
Predef
에는
String
을 각각
의 래퍼 타입으로 변환하는 메서드가 들어 있다.
implicit def wrapString
(
s
:
String
):
WrappedString
implicit def unwrapString
(
ws
:
WrappedString
):
String
implicit def augmentString
(
x
:
String
):
StringOps
implicit def unaugmentString
(
x
:
StringOps
):
String
NOTE
_
WrappedArray
/
ArrayOps
나
WrappedString
/
StringOps
와 같이 래퍼 타입이 쌍으로 존재하
는 것은 조금 혼란스럽다. 하지만 다행히 암시적 변환은 자동으로 호출되며, 필요한 메서드에 따라 정확한 래
퍼 타입을 선택해준다.
자바의 기본 타입을 박싱한 타입과 스칼라의
AnyVal
타입 사이를 변환하는 메서드도 있다. 이런
메서드는 자바와의 상호 운용을 더 쉽게 만들어준다.
implicit def byte2Byte
(
x
:
Byte
)
=
java
.
lang
.
Byte
.
valueOf
(
x
)
implicit def short2Short
(
x
:
Short
)
=
java
.
lang
.
Short
.
valueOf
(
x
)
implicit def char2Character
(
x
:
Char
)
=
java
.
lang
.
Character
.
valueOf
(
x
)
implicit def int2Integer
(
x
:
Int
)
=
java
.
lang
.
Integer
.
valueOf
(
x
)
implicit def long2Long
(
x
:
Long
)
=
java
.
lang
.
Long
.
valueOf
(
x
)
implicit def float2Float
(
x
:
Float
)
=
java
.
lang
.
Float
.
valueOf
(
x
)
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.