암시적 변환
암시적 변환 (Implicit Conversions)
암시적 변환은 scala.Conversion 클래스의 given 인스턴스로 정의해요. 이 클래스는 scala 패키지에 다음과 같이 정의되어 있어요.
abstract class Conversion[-T, +U] extends (T => U):
def apply (x: T): U
예를 들어 String에서 Token으로의 암시적 변환은 이렇게 써요.
given Conversion[String, Token]:
def apply(str: String): Token = new KeyWord(str)
별칭(alias)을 쓰면 더 간결하게 표현할 수 있어요.
given Conversion[String, Token] = new KeyWord(_)
암시적 변환은 세 가지 상황에서 컴파일러에 의해 자동으로 적용돼요.
- 식
e의 타입이T인데T가 그 식의 기대 타입S에 부합하지 않을 때. e가 타입T인 선택e.m에서,T가m이라는 멤버를 정의하지 않을 때.e가 타입T인 애플리케이션e.m(args)에서,T가 이름m의 멤버를 (일부) 정의하지만 그중 어느 것도 인자args에 적용될 수 없을 때.
첫 번째 경우 컴파일러는 타입 T의 인자를 타입 S에 매핑하는 given scala.Conversion 인스턴스를 찾아요. 두 번째와 세 번째 경우에는 args가 있으면 그에 적용될 수 있는 멤버 m을 정의하는 타입으로 타입 T의 인자를 매핑하는 given scala.Conversion 인스턴스를 찾아요. 그런 인스턴스 C를 찾으면 식 e는 C.apply(e)로 대체돼요.
본문
예시 (Examples)
Predef 패키지에는 기본 숫자 타입을 java.lang.Number의 하위 클래스에 매핑하는 "auto-boxing" 변환들이 들어 있어요. 예를 들어 Int에서 java.lang.Integer로의 변환은 다음과 같이 정의할 수 있어요.
given int2Integer: Conversion[Int, java.lang.Integer] =
java.lang.Integer.valueOf(_)
"마그넷(magnet)" 패턴은 메서드의 많은 변형을 표현할 때 쓰이기도 해요. 메서드의 오버로드 버전을 정의하는 대신, 메서드가 특별히 정의된 "마그넷" 타입의 인자를 하나 이상 받게 하고, 다양한 인자 타입을 그 타입으로 변환할 수 있게 해요. 예시를 볼게요.
object Completions:
// The argument "magnet" type
enum CompletionArg:
case Error(s: String)
case Response(f: Future[HttpResponse])
case Status(code: Future[StatusCode])
object CompletionArg:
// conversions defining the possible arguments to pass to `complete`
// these always come with CompletionArg
// They can be invoked explicitly, e.g.
//
// CompletionArg.fromStatusCode(statusCode)
given fromString : Conversion[String, CompletionArg] = Error(_)
given fromFuture : Conversion[Future[HttpResponse], CompletionArg] = Response(_)
given fromStatusCode: Conversion[Future[StatusCode], CompletionArg] = Status(_)
end CompletionArg
import CompletionArg.*
def complete[T](arg: CompletionArg) = arg match
case Error(s) => ...
case Response(f) => ...
case Status(code) => ...
end Completions
이 설정은 complete를 단순히 오버로드하는 것보다 복잡하지만, 일반 오버로드를 쓸 수 없을 때(위 경우처럼 Future[...] 인자를 받는 오버로드 메서드를 둘 가질 수 없으니까)나 일반 오버로드가 변형의 조합 폭발을 일으킬 때는 여전히 유용할 수 있어요.