257
5
암시
타입이 호환될 있는 경우가 여러 가지 있을 있다. 이때 가장 구체적인 타입이 선택된다.
를 들어 암시적 인자의 타입이
Foo
라면, 범위 안에 들어 있는
Foo
타입의 암시적 값이
AnyRef
타입의 암시적 값보다 우선적으로 선택된다.
이상의 암시적 값이 모호하다면(예를 들어 구체적인 타입이 같기 때문에 ) 컴파일러 오류가
발생한다.
컴파일러는 항상 일부 라이브러리 암시를 범위에 넣는 반면, 다른 라이브러리 암시는 반드시
임포트해야 사용할 있다. 이제 이런 암시에 대해 살펴보자.
5.7
스칼라가 기본 제공하는 암시
스칼라
2
.
11
라이브러리의 소스 코드에는
300
개 이상의 암시 메서드, 값, 타입이 들어 있다.
그중 대부분은 메서드며, 그런 메서드 중 대부분은 한 타입을 다른 타입으로 변환하기 위해
용된다. 어떤 암시가 여러분 코드에 영향을 끼칠지 아는 것이 중요하다. 따라서 여기서는 암시적
값을 그룹별로 나눠서 논한다. 모든 자세한 사항을 아는 것은 전혀 중요하지 않다. 하지만 어떤
암시가 존재하는지에 대해 잡는 것은 도움이 것이다. 따라서 이번 절은 대강 살펴봐도
된다.
컬렉션의
CanBuildFrom
타입에 대해서는 이미 살펴봤다. 이와 비슷한
CanCombineFrom
타입은
이름이 암시하는 대로 인스턴스를 조합할 사용한다. 정의에 대해서는 따로 설명하지
것이다.
AnyVal
타입의 모든 동반 객체에는
Int
에서
Long
으로 변환하는 것과 같은 확장 변환
widening
conversion
들어 있다. 대부분은 다음 예와 같이 그냥 해당 타입에 대해
toX
메서드를 호출한다.
object Int
{
...
implicit def int2long
(
x
:
Int
):
Long
=
x
.
toLong
...
}
258
2
기본기 다지기
다음 코드는 이런
AnyVal
암시 변환을 보여준다. 이런 암시 변환으로 인해 스칼라에서는 다른
언어에서는 필요한 타입 변환을 구현할 필요가 없다.
Byte
(
http
://
bit
.
ly
/
1s0S3Gk
) 동반 객체에 있는 암시는 다음과 같다.
implicit def byte2short
(
x
:
Byte
):
Short
=
x
.
toShort
implicit def byte2int
(
x
:
Byte
):
Int
=
x
.
toInt
implicit def byte2long
(
x
:
Byte
):
Long
=
x
.
toLong
implicit def byte2float
(
x
:
Byte
):
Float
=
x
.
toFloat
implicit def byte2double
(
x
:
Byte
):
Double
=
x
.
toDouble
Char
(
http
://
bit
.
ly
/
1wOfGWV
) 동반 객체에 있는 암시는 다음과 같다.
implicit def char2int
(
x
:
Char
):
Int
=
x
.
toInt
implicit def char2long
(
x
:
Char
):
Long
=
x
.
toLong
implicit def char2float
(
x
:
Char
):
Float
=
x
.
toFloat
implicit def char2double
(
x
:
Char
):
Double
=
x
.
toDouble
Short
(
http
://
bit
.
ly
/
1E8xY8y
) 동반 객체에 있는 암시는 다음과 같다.
implicit def short2int
(
x
:
Short
):
Int
=
x
.
toInt
implicit def short2long
(
x
:
Short
):
Long
=
x
.
toLong
implicit def short2float
(
x
:
Short
):
Float
=
x
.
toFloat
implicit def short2double
(
x
:
Short
):
Double
=
x
.
toDouble
Int
(
http
://
bit
.
ly
/
1wOaKCf
) 동반 객체에 있는 암시는 다음과 같다.
implicit def int2long
(
x
:
Int
):
Long
=
x
.
toLong
implicit def int2float
(
x
:
Int
):
Float
=
x
.
toFloat
implicit def int2double
(
x
:
Int
):
Double
=
x
.
toDouble
Long
(
http
://
bit
.
ly
/
1yMo2P4
) 동반 객체에 있는 암시는 다음과 같다.
259
5
암시
implicit def long2float
(
x
:
Long
):
Float
=
x
.
toFloat
implicit def long2double
(
x
:
Long
):
Double
=
x
.
toDouble
Float
(
http
://
bit
.
ly
/
1toBg4x
) 동반 객체에 있는 암시는 다음과 같다.
implicit def float2double(x: Float): Double = x.toDouble
scala
.
math
의 타입인
BigInt
BigDecimal
에는
AnyVal
타입 대부분과 그에 상응하는 자바
구현으로부터 각각으로 변환하는 암시가 들어 있다.
BigDecimal
(
http
://
bit
.
ly
/
13p5R89
) 동반 객체에 있는 암시는 다음과 같다.
implicit def int2bigDecimal
(
i
:
Int
):
BigDecimal
=
apply
(
i
)
implicit def long2bigDecimal
(
l
:
Long
):
BigDecimal
=
apply
(
l
)
implicit def double2bigDecimal
(
d
:
Double
):
BigDecimal
=
...
implicit def javaBigDecimal2bigDecimal
(
x
:
BigDec
):
BigDecimal
=
apply
(
x
)
apply
를 호출하면
BigDecimal
.
apply
팩토리 메서드를 호출한다. 이런 메서드 호출을 대신할
있는 암시가 있으면 편리하다.
BigInt
(
http
://
bit
.
ly
/
10ao7jo
)동반 객체에 있는 암시는 다음과 같다.
implicit def int2bigInt
(
i
:
Int
):
BigInt
=
apply
(
i
)
implicit def long2bigInt
(
l
:
Long
):
BigInt
=
apply
(
l
)
implicit def javaBigInteger2bigInt
(
x
:
BigInteger
):
BigInt
=
apply
(
x
)
Option
(
http
://
bit
.
ly
/
1G2G30k
)원소가 없거나 하나인 리스트로 변환할 있다.
implicit def option2Iterable[A](xo: Option[A]): Iterable[A] = xo.toList
260
2
기본기 다지기
스칼라는
Array
[
T
]
String
포함한 여러 가지 자바 타입을 사용한다. 배열과 문자열에 대해
모든 스칼라 컬렉션이 공통으로 제공하는 메서드를 정의하는
ArrayOps
[
T
]
StringOps
타입
있다. 따라서 이런 래퍼 타입으로 변환하거나, 래퍼 타입을 원래 타입으로 변환하는 암시 변환
유용하다. 스칼라가 제공하는 추가 연산은 이름에
Wrapper
들어가는 타입에 정의되어 있다.
대부분은
Predef
(
http
://
bit
.
ly
/
11QI0fF
)정의되어 있다. 정의 일부는
@
inline
(
http
://
bit
.
ly
/
1u1jIMU
) 애노테이션이 붙어 있다. 그래서 컴파일러는 해당 메서드 호출을
라이닝해서 (메서드 호출 코드 대신 그 메서드 본문을 삽입하는 방식으로) 스택 프레임을 낭비
하지 않도록 만든다. 컴파일러가 메서드 호출을 인라이닝하지 못하게 하는
@
noinline
(
http
://
bit
.
ly
/
10aoavB
) 애노테이션도 있다.
몇몇 메서드는 타입을 다른 타입으로 변환한다. 예를 들어 어떤 타입을 감싼 타입을 통해
추가 메서드를 제공하는 경우 그런 변환을 사용한다.
@
inline implicit def augmentString
(
x
:
String
):
StringOps
=
new StringOps
(
x
)
@
inline implicit def unaugmentString
(
x
:
StringOps
):
String
=
x
.
repr
implicit def tuple2ToZippedOps
[
T1
,
T2
](
x
:
(
T1
,
T2
))
=
new runtime
.
Tuple2Zipped
.
Ops
(
x
)
implicit def tuple3ToZippedOps
[
T1
,
T2
,
T3
](
x
:
(
T1
,
T2
,
T3
))
=
new runtime
.
Tuple3Zipped
.
Ops
(
x
)
implicit def genericArrayOps
[
T
](
xs
:
Array
[
T
]):
ArrayOps
[
T
]
=
...
implicit def booleanArrayOps
(
xs
:
Array
[
Boolean
]):
ArrayOps
[
Boolean
]
=
=
new ArrayOps
.
ofBoolean
(
xs
)
...
//
다른
AnyVal
타입에
대해서도
비슷한
함수가
있다
.
implicit def refArrayOps
[
T
<
:
AnyRef
](
xs
:
Array
[
T
]):
ArrayOps
[
T
]
=
new ArrayOps
.
ofRef
[
T
](
xs
)
@
inline implicit def byteWrapper
(
x
:
Byte
)
=
new runtime
.
RichByte
(
x
)
...
//
다른
AnyVal
타입에
대해서도
비슷한
함수가
있다
.
implicit def genericWrapArray
[
T
](
xs
:
Array
[
T
]):
WrappedArray
[
T
]
=
...
implicit def wrapRefArray
[
T
<
:
AnyRef
](
xs
:
Array
[
T
]):
WrappedArray
[
T
]
=
...
implicit def wrapIntArray
(
xs
:
Array
[
Int
]):
WrappedArray
[
Int
]
=
...
...
//
다른
AnyVal
타입에
대해서도
비슷한
함수가
있다
.
implicit def wrapString
(
s
:
String
):
WrappedString
=
...
implicit def unwrapString
(
ws
:
WrappedString
):
String
=
...

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.