[Scala 필기-도]Scala 암시 적 Implicit
21655 단어 Scala
암시 적 인 것 은 도대체 무엇 입 니까?
scala 중 은 식 은 자바 에 비해 새로운 특성 이다.그렇다면 암시 적 인 것 은 무엇 일 까?암시 적 존재 세 가지 기본 사용 방식:-암시 적 속성-암시 적 방법-암시 적 대상
암시 적 속성 예:
implicit val int size = 5
def caculate(a : Int)(implicit val size) = a * size
이런 상황 에서 암시 적 인 것 은 문맥 속성 으로 입력 하 는 것 이 고 더욱 복잡 한 상황 은 앞에서 말 한 문맥 과 기능 통 제 를 수행 하 는 것 과 같다.그 본질은 자원 의 주입 으로 자원 의 디 스 플레이 설정 을 숨 기거 나 생략 하여 불 러 오 는 목적 을 달성 하 는 것 이다.여기까지 말 하면 Spring 의 IOC 를 쉽게 연상 시 킬 수 있다 고 믿 습 니 다.Spring/Guice 의 IOC 에서 우 리 는 주해/배치 라 는 형식 을 통 해 자원 주입 실례 화 를 실현 합 니 다.Spring/Guice 에서 주 입 된 자원 에 대해 우 리 는 xml 또는 주 해 를 통 해 자원 속성 설정 을 완성 할 수 있 습 니 다.그러나 이러한 방법 은 부족 합 니 다.xml 또는 주해 설정 은 모두 정적 설정 에 속 합 니 다.만약 에 우리 가 동적 특성 이 필요 할 때 추가 로 많은 작업 을 해 야 합 니 다.예 를 들 어 우 리 는 지불 컨트롤 러 가 있 는데 지불 방식 이 달러 일 때 우 리 는 달러 서 비 스 를 사용 해 야 한다.지불 방식 이 인민 폐 를 위해 서 우 리 는 인민폐 서 비 스 를 사용 해 야 한다.
class PayController @Inject()settlementService: SettlementService) { // ,
def doSettle(bill: Bill) = {
settlementService.doSettle(bill)
}
}
이러한 결 제 를 실현 하려 면 코드 를 통 해 bill.getType 을 판단 한 후 수 동 으로 해당 하 는 결제 기능 을 실현 해 야 합 니 다.하지만 이렇게 결합 을 도입 했다.
한편,암시 적 속성 은 더 좋 은 방식 임 에 틀림없다.여기 서 결제 방식 을 자 유 롭 게 주입 할 수 있다.
class PayController ()(implicit val settlementService: SettlementService) {
def doSettle(bill: Bill) = {
settlementService.doSettle(bill)
}
}
함수 방법 은 본질 적 으로 일종 의 전환 을 하 는 것 이다.이런 전환 은 문맥 에 의존 하지 않 는 다.즉,f(a)=>b 는 다른 상태 에 영향 을 주지 않 고 부작용 이 없다 고 할 수 있다.암시 적 함수 방법 은 본질 적 으로 함수 방법 이기 도 하고 요소 에 대한 전환 관계 로 볼 수 있 으 며 a=>b.자바 에서 facade 모드 는 비교적 자주 사용 하 는 모드 로 facade 모드 는 인터페이스 정보 에 대한 패 키 징 을 제공 합 니 다.시스템 개발 이나 업무 개발 에서 facade 모델 은 사용 이 비교적 빈번 합 니 다.자바 에서 우 리 는 서로 다른 시스템 인터페이스 에 대응 하여 서로 다른 facade 를 제공 할 수 있 지만 서로 다른 facade 의 전환 에 대해 코드 에 수 동 으로 장 착 해 야 합 니 다.방법 급 암시 적 전환 을 통 해 우 리 는 인터페이스 급 의 암시 적 전환 을 편리 하 게 실현 할 수 있다.
예 를 들 어 다음 글 에서 저 희 는 주문 서 를 확대 하고 실제 결 제 된 주문 서 는 온라인 과 오프라인 두 가지 주문 과 관련 될 수 있 지만 최종 주문 정 보 는 내부 의 BillInfo 로 전 환 됩 니 다.여기 서 우 리 는 방법 급 암시 적 전환 을 통 해 OnlineBillFacade/OfflineBillFacade=>BillInfo 를 직접 실현 하고 코드 를 대량으로 판단 하지 않 아 도 논리 적 통 제 를 실현 합 니 다.
sealed trait Bill
case class OnlineBillFacade(count: Int,
platform: Platform,
currency: Currency) extend Bill
case class OfflineBillFacade(count: Int,
address: String,
shop: Shop,
currency: Currency) extend Bill
case class BillInfo(
flowNumber: Long,
createTime: Long,
state: State,
count: Int,
platform: Platform,
address: String,
shop: Shop,
currency: Currency) extend Bill
object BillConverter {
implicit def onlineBill2BillInfo(facade: OnlineBillFacade) : BillInfo = ...
implicit def offlineBillFacade(facade: OfflineBillFacade) : BillInfo = ...
}
class PayController ()(implicit val settlementService: SettlementService) {
def doSettle[T <: bill="" t="" settlementservice.dosettle=""/>
암시 적 대상 에 대해 AOP 사상 에 대한 진일보 한 탐색 임 에 틀림없다.AOP 에서 우 리 는 소스 코드 를 바 꾸 지 않 고 기능 을 추가 하려 고 합 니 다.AOP 에서 우 리 는 동적 대 리 를 통 해 기능 의 확장 을 실현 합 니 다.동적 대 리 를 통 해 우 리 는 절단면 통 제 를 편리 하 게 실현 할 수 있다.절단면 을 대상 으로 프로 그래 밍 하 는 것 은 실제 적 으로 우리 의 모든 것 이 인 터 페 이 스 를 중심 으로 디자인 해 야 한 다 는 전제 가 있다.절단면 이 제어 할 수 있 는 최소 입도 가 바로 방법 급 이다.또한 범 형 설정 이기 때문에 사실상 절단면 에서 알림 을 사용 하려 면 입력 매개 변 수 를 선별 판단 하여 범 형 관 리 를 완성 해 야 한다.이 부분 은 확장 에 불리 하 다.사실은 여기 서 우 리 는 범 형 에 대해 유형 적 인 제약 을 할 방법 이 없다.
한편,암시 적 대상 은 우리 에 게 새로운 가능성 을 가 져 다 주 었 다.암시 적 대상 은 POJO 를 대상 으로 하기 때문에 암시 적 대상 은 AOP 에 비해 더욱 가 는 입도 통 제 를 가진다.또한 POJO 를 대상 으로 하기 때문에 암시 적 대상 은 경계 정 의 를 할 필요 가 없다.암시 적 대상 을 통 해 우 리 는 기 존 코드 를 바 꾸 지 않 고 기능 의 확장 을 실현 할 수 있다.
활용 단어 참조
통용 되 는 상하 문 정 보 는 은 식
을 통 해 결합 을 낮 춘 다트 랜 잭 션,데이터베이스 연결,스 레 드 풀,사용자 세 션 을 작성 할 때 암시 적 매개 변수 컨 텍스트 도 사용 하기에 적합 합 니 다.방법 매개 변 수 를 사용 하면 행 위 를 조합 할 수 있 고 방법 매개 변 수 를 암시 적 매개 변수 로 설정 하면 API 를 더욱 간결 하 게 만 들 수 있다.
//
import scala.concurrent.ExecutionContext.Implicits.global
apply[T](body: => T)(implicit executor: ExecutionContext): Future[T]
기능 제어
권한 수여 토 큰 을 도입 함으로써 저 희 는 특정한 API 작업 을 일부 사용자 만 호출 할 수 있 도록 제어 할 수 있 습 니 다.저 희 는 권한 수여 토 큰 을 사용 하여 데이터 의 가시 성 을 결정 할 수 있 습 니 다.또한 암시 적 사용자 세 션 매개 변 수 는 이러한 토 큰 정 보 를 포함 할 수 있 습 니 다.
def createMenu(implicit session: Session): Menu = {
val defaultItems = List(helpItem, searchItem)
val accountItems =
if (session.loggedin()) List(viewAccountItem, editAccountItem)
else List(loginItem)
Menu(defaultItems ++ accountItems)
}
사용 가능 한 인 스 턴 스 제한
매개 변수 화 유형 방법 이 있 는 유형 매개 변 수 를 한정 하여 이 매개 변 수 는 특정한 유형의 입력 만 받 도록 합 니 다.
package implicits
object Implicits {
import implicits.javadb.JRow
implicit class SRow (jrow: JRow){
def get[T](colName: String)(implicit toT: (JRow, String) => T): T =
toT(jrow, colName)
}
implicit val jrowToInt: (JRow, String) => Int = (jrow: JRow, colName: String) => jrow.getInt(colName)
implicit val jrowToDouble: (JRow, String) => Double = (jrow: JRow, colName: String) => jrow.getDouble(colName)
implicit val jrowToString: (JRow, String) => String = (jrow: JRow, colName: String) => jrow.getText(colName)
def main(args: Array[String]) = {
val row = javadb.JRow("one" -> 1, "two" -> 2.2, "three" -> "THREE!")
val oneValue1: Int = row.get("one")
val twoValue1: Double = row.get("two")
val threeValue1: String = row.get("three")
// val fourValue1: Byte = row.get("four")
//
println(s"one1 -> $oneValue1")
println(s"two1 -> $twoValue1")
println(s"three1 -> $threeValue1")
val oneValue2 = row.get[Int]("one")
val twoValue2 = row.get[Double]("two")
val threeValue2 = row.get[String]("three")
// val fourValue2 = row.get[Byte]("four")
//
println(s"one2 -> $oneValue2")
println(s"two2 -> $twoValue2")
println(s"three2 -> $threeValue2")
}
}
package database_api {
case class InvalidColumnName(name: String)
extends RuntimeException(s"Invalid column name $name")
trait Row {
def getInt (colName: String): Int
def getDouble (colName: String): Double
def getText (colName: String): String
}
}
package javadb {
import database_api._
case class JRow(representation: Map[String, Any]) extends Row {
private def get(colName: String): Any =
representation.getOrElse(colName, throw InvalidColumnName(colName))
def getInt (colName: String): Int = get(colName).asInstanceOf[Int]
def getDouble (colName: String): Double = get(colName).asInstanceOf[Double]
def getText (colName: String): String = get(colName).asInstanceOf[String]
}
object JRow {
def apply(pairs: (String, Any)*) = new JRow(Map(pairs :_*))
}
}
암시 적 증거
때때로 우 리 는 허용 되 는 유형 만 한정 하고 추가 처 리 를 제공 할 필요 가 없다.다시 말 하면 우 리 는 제시 한 유형 이 우리 의 수 요 를 만족 시 킬 수 있다 는'증거'가 필요 하 다.이제 우 리 는 또 다른 암시 적 증거 라 고 불 리 는 관련 기술 에 대해 허용 되 는 유형 을 한정 하고 이런 유형 들 은 모두 있 는 초 류 를 계승 할 필요 가 없다.
trait TraversableOnce[+A] ... {
...
def toMap[T, U](implicit ev: <: class="hljs-literal">T, U)]): immutable.Map[T, U]
...
}
우 리 는 두 가지 유형의 매개 변수 로 구 성 된 유형 을 접두사 표현법 으로 표시 할 수 있다 고 언급 한 적 이 있 습 니 다.따라서 다음 두 가지 표현 식 은 등가 입 니 다.<:b=">A<:b=">는 toMap 에서 B 는 실제 pair:<:u=">입 니 다.
형식 지우 기
object M {
implicit object IntMarker
implicit object StringMarker
def m(seq: Seq[Int])(implicit i: IntMarker.type): Unit = println(s"Seq[Int]: $seq")
def m(seq: Seq[String])(implicit s: StringMarker.type): Unit =
println(s"Seq[String]: $seq")
}
가상 유형 Phantom Type
형식 지우 기 와 유사 합 니 다.가상 형식 은 태그 에 만 사 용 됩 니 다.
가상 유형 자 체 는 실제 적 으로 암시 적 전환 의 범주 에 속 하지 않 지만 여 기 는 사실 유형 지우 기 와 사용 에 있어 어느 정도 비슷 한 초기 가 있다.
가상 유형 은 주로 다음 과 같은 두 가지 장점 이 있 습 니 다.-무효 상 태 를 대표 할 수 없습니다.가장 좋 은 표현 은 List,Cons 와 Nil 의 관계 입 니 다.-유형 등급 의 정 보 를 가지 고 다 니 는 것 입 니 다.
예 를 들 어 가상 유형 을 통 해 거리 단 위 를 제한 하 는 것 이다.
case class Distance[A](x: Double) extends AnyVal
case object Kilometer
case object Mile
def marathonDistance: Distance[Kilometer.type] = Distance[Kilometer.type](42.195)
def distanceKmToMiles(kilos: Distance[Kilometer.type]): Distance[Mile.type] =
Distance[Mile.type](kilos.x * 0.621371)
def marathonDistanceInMiles: Distance[Mile.type] = distanceKmToMiles( marathonDistance )
암시 적 오류 보고
@implicitNotFound(msg =
"Cannot construct a collection of type ${To} with elements of type ${Elem}" +
" based on a collection of type ${From}.")
trait CanBuildFrom[-From, -Elem, +To] {...}
유형 클래스 모드
자바 서브 타 입 다 형 과 달리 이 기능 도 특설 다 형(ad hoc polymorphism)scala 자바 의 매개 변수 화 다 형(paremetric polymorphism)이 되 었 습 니 다.
case class Address(street: String, city: String)
case class Person(name: String, address: Address)
trait ToJSON {
def toJSON(level: Int = 0): String
val INDENTATION = " "
def indentation(level: Int = 0): (String,String) =
(INDENTATION * level, INDENTATION * (level+1))
}
implicit class AddressToJSON(address: Address) extends ToJSON {
def toJSON(level: Int = 0): String = {
val (outdent, indent) = indentation(level)
s"""{
|${indent}"street": "${address.street}",
|${indent}"city":
"${address.city}"
|$outdent}""".stripMargin
}
}
implicit class PersonToJSON(person: Person) extends ToJSON {
탐구 암시 적
상기 사용 장면 에서 말 한 바 와 같이 암시 적 인 것 은 scala 에서 우리 에 게 많은 놀 라 움 을 가 져 다 주 었 다.암시 적 인 방식 을 통 해 우 리 는 문맥 처리,경계 처리,유형 지우 기 등 문 제 를 더욱 잘 해결 할 수 있다.
암시 적 부족
왜 간단 한 유형+유형 클래스 모드 가 적용 되 지 않 습 니까?
trait Stringizer[+T] {
def stringize: String
}
implicit class AnyStringizer(a: Any) extends Stringizer[Any] {
def stringize: String = a match {
case s: String => s
case i: Int => (i*10).toString
case f: Float => (f*10.1).toString
case other =>
throw new UnsupportedOperationException(s"Can't stringize $other")
}
}
val list: List[Any] = List(1, 2.2F, "three", 'symbol)
list foreach { (x:Any) =>
try {
println(s"$x: ${x.stringize}")
} catch {
case e: java.lang.UnsupportedOperationException => println(e)
}
}
우 리 는 Stringizer 라 는 추상 체 를 정의 했다.이전 ToJSON 예제 대로 라면 문자열 화 되 기 를 원 하 는 모든 형식 에 암시 적 클래스 를 만 들 것 입 니 다.그 자체 가 문제 다.만약 우리 가 서로 다른 유형의 인 스 턴 스 를 처리 하고 싶다 면,우 리 는 list 형식의 map 방법 에서 Stringizer 인 스 턴 스 를 암시 적 으로 전달 할 수 밖 에 없습니다.따라서 우 리 는 AnyStringerize 류 를 정의 해 야 합 니 다.이 종 류 는 우리 가 알 고 있 는 모든 유형 을 어떻게 처리 하 는 지 알 고 있 습 니 다.이 유형 들 은 이상 한 default 자 구 를 던 지 는 데 도 포함 되 어 있다.이러한 실현 방식 은 매우 아름 답지 않 고 대상 을 대상 으로 프로 그래 밍 하 는 핵심 규칙 에 도 위배 된다.switch 문 구 를 사용 하여 변화 할 수 있 는 유형 을 판단 해 서 는 안 된다.반면,다 중 배포 작업 을 이용 해 야 합 니 다.이 는 toString 방법 이 Scala 와 자바 언어 에서 의 운영 방식 과 유사 합 니 다.
암시 적 사용 주의
예 를 들 어 특정한 유형의 정의 방법+를 사용 하고 이 방법 을 해당 유형의 인 스 턴 스 에 적용 하려 고 한다 면 컴 파일 러 는 이 인 스 턴 스 의 toString 방법 을 호출 하여 String 형식의+작업(문자열 통합)을 수행 할 수 있 습 니 다.이것 은 특정한 상황 에서 String 과 같은 잘못된 유형의 이상 한 오 류 를 설명 할 수 있다.
이와 함께 필요 하 다 면 컴 파일 러 는 방법의 입력 매개 변 수 를 자동 으로 원 그룹 으로 조합 할 것 이다.때때로 이 행 위 는 사람 을 괴 롭 힐 수 있다.다행히도 스칼라 2.11 은 현재 경고 메 시 지 를 던 질 것 이다.
scala> def m(pair:Tuple2[Int,String]) = println(pair)
scala> m(1, "two")
:9: warning: Adapting argument list by creating a 2-tuple:
this may not be what you want.
signature: m(pair: (Int, String)): Unit
given arguments: 1, "two"
after adaptation: m((1, "two"): (Int, String))
m(1,"two")
암시 적 해석 규칙
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
sbt-native-packager로 docker 이미지의 기반을 amazoncorretto로 만들고 싶습니다.build.sbt에 다음을 추가합니다. 그런데 에서 빌드하려고하면 같은 오류가 발생하여 실패합니다 생성 된 Dockerfile을 들여다 보면 같은 행이 있습니다. 이지만 amazonlinux에서는 addgroup 또...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.