play framework로 이런저런 작업과 스칼라 관련 모임에서 코드를 보는 와중에
implicit 키워드가 눈에 자주 보인다.
나중에 혼란스러워 하지말고 미리 정리.
- implicit parameter
(참고 : https://docs.scala-lang.org/ko/tutorials/tour/implicit-parameters.html.html
먼저 메인 클래스를 선언한다.
object HelloWorld {
def main(args: Array[String]): Unit = {
println("hello, world!")
}
def testFunction(name : String)(implicit liveObject : LiveObject) : Unit = {
println("I am " + name)
liveObject.introduce();
}
}
간단하다, Hello, world 문자열하나만 보여준다. testFunction 은 implicit 파라미터로 LiveObject 를 사용중이다.
testFunction 은 지금 당장은 사용하지 않으니 "이런게 있구나" 수준으로 넘어가자.
trait의 내용은 아래와 같다.
trait LiveObject {
def introduce() = {
println("I am LiveObject")
}
}
이제 LiveObject 를 믹스인한 클래스 두 개를 생성한다.
class Animal extends LiveObject {
override def introduce(): Unit = {
println("I am Animal")
}
}
class Human extends LiveObject {
override def introduce(): Unit = {
println("I am Human")
}
}
간단하다 introduce 를 재정의 해서 문자열 하나만 다르게 재정의 했다.
준비작업은 모두 끝났다. 이제 main 함수 내에서 testFunction 을 호출을... 했는데? 어라? 에러가 있네?
에러 내용을 자세히 보면
직접 넣어줄 수는 있다.. 근데 이건 '암시적' 아닌 것 같아 다른 방법을 찾아본다.
바로 위에 Animal 변수를 하나 추가해준다.. 이러면 돌아가겠지.
object HelloWorld {
def main(args: Array[String]): Unit = {
println("hello, world!")
val animal = new Animal
testFunction("thomas")
}
def testFunction(name : String)(implicit liveObject : LiveObject) : Unit = {
println("I am " + name)
liveObject.introduce()
}
}
여전히 에러가 난다.
암시적 파라미터 관련 스칼라 문서를 다시 읽어보면...
스칼라 컴파일러는 implicit 파라미터를 만났을 때, 실제 파라미터에 할당할 변수를 검색하는데 규칙은 다음과 같다.
1. 메서드가 호출되었을 때, prefix 없이 접근할 수 있는 변수 (당연히 변수들은 implicit 키워드가 붙어야 함.)
2. implicit 키워드가 붙은 암시적 파라미터와 관련된 모든 멤버
2번은 조금 어려우니 일단 1번부터, 암시적 파라미터를 설정하려면 implicit 을 붙여야 한다. 변수를 implicit 으로 변경해서 다시.
object HelloWorld {
def main(args: Array[String]): Unit = {
println("hello, world!")
implicit val animal = new Animal
testFunction("thomas")
}
def testFunction(name : String)(implicit liveObject : LiveObject) : Unit = {
println("I am " + name)
liveObject.introduce()
}
}
이번엔 실행이 제대로 된다.
hello, world!
I am thomas
I am Animal
Process finished with exit code 0
암시적 변수 / 함수를 선언하려면 implicit 키워드를 사용하여 선언해야 정상적으로 인식하는듯
그러면 이번에 같은 type 을 두 개 넣으면 어떻게 될까?
def main(args: Array[String]): Unit = {
println("hello, world!")
implicit val animal = new Animal
implicit val human = new Human
testFunction("thomas")
}
실행 해보니 아래와 같은 Exception 이 발생한다.
머릿속에 어느정도 그림이 그려진다.
implicit 파라미터는 "함수가 호출 된 타이밍" 에 prefix 없이 접근 가능한 변수 중 "가장 가까운 변수 " 가 할당되다 라고 이해하면 빠를듯.
다음번엔 implicit function 을 좀 더 봐야겠다.
2019년 11월 18일 추가
변수의 scope 가 다를경우 같은 타입의 implicit 의 선언이 가능하다. 이 경우에 가장 최근에 선언된 implicit 변수가 사용된다.
object HelloWorld {
def main(args: Array[String]): Unit = {
println("hello, world!")
implicit val human = new Human
overlapfunction()
}
def overlapfunction()(implicit liveObject : LiveObject) : Unit = {
implicit val animal = new Animal
testFunction("thomas")
}
def testFunction(name : String)(implicit liveObject : LiveObject) : Unit = {
println("I am " + name)
liveObject.introduce()
}
}
위 코드를 실행하면 아래와 같은 결과가 나온다.
hello, world!
I am thomas
I am Animal
'프로그래밍 > Scala' 카테고리의 다른 글
[Slick] DateTime 로딩 시 오류. (0) | 2020.04.05 |
---|---|
Scala 로 뭔가 만들기 위해 필요한 것. (0) | 2020.03.18 |
akka 초반 간략정리. (0) | 2020.02.09 |
Typing Rules for Functions (0) | 2020.02.02 |
Covariant, Contravariant 그림으로 다시 정리 (0) | 2020.02.02 |
Covariant, Contravariant 정리 (0) | 2020.02.02 |
[스칼라] Slick 오류 처리 (0) | 2017.03.26 |
[스칼라] 커링(Currying) - 아마도 첫번째 글. (0) | 2017.02.26 |