복붙노트

[SCALA] 매개 변수 유형 스칼라 asInstanceOf

SCALA

매개 변수 유형 스칼라 asInstanceOf

내가 캐스트가를 입력 할 수있는 함수를 작성하고 싶습니다 A는 될 수있는 예를 들어, 목록 [지능], 또는 맵 [INT, 목록 [지능]]와 같은 더 복잡한 파라미터 화 된 형태.

def castToType[A](x: Any): A = {
  // throws if A is not the right type
  x.asInstanceOf[A]
}

유형이 정확하지 않은 경우에도 지금 (내가 믿는) 삭제를 입력하기 때문에,이 코드는 명랑하게 작동합니다. 오류 액세스 만 매니페스트, witha의의는 ClassCastException.

val x = List(1, 2, 3)
val y = castToType[List[String]](x)
y(0) --> throws java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

내가 제대로이 작품을 만들기 위해 매니페스트를 사용할 수있는 방법이 있나요? 감사!

해결법

  1. ==============================

    1.불행하게도, asInstanceOf의 고유 제한이. 나는 실제로 세부 사항을 언급 scaladoc을보고 놀라게하고 있습니다 :

    불행하게도, asInstanceOf의 고유 제한이. 나는 실제로 세부 사항을 언급 scaladoc을보고 놀라게하고 있습니다 :

    당신은 주로 사용자의 DB / memcached를 인터페이스에서 물건을 다시 가져올 때 가능성이 주요 문제가 될 것입니다에 이동에 대한 잘못된 캐스트에 빠른 실패에 대해 우려하는 경우, 나는에 이동 객체의 머리의 캐스팅을 강제 주위를 연주했다 :

    def failFastCast[A: Manifest, T[A] <: Traversable[A]](as: T[A], any: Any) = { 
      val res = any.asInstanceOf[T[A]]
      if (res.isEmpty) res 
      else { 
        manifest[A].newArray(1).update(0, res.head) // force exception on wrong type
        res
      }
    }
    

    간단한 예에 그것은 작동합니다 :

    scala> val x = List(1, 2, 3): Any
    x: Any = List(1, 2, 3)
    
    scala> failFastCast(List[String](), x)
    java.lang.ArrayStoreException: java.lang.Integer
    [...]
    
    scala> failFastCast(List[Int](), x)
    res22: List[Int] = List(1, 2, 3)
    

    하지만 좀 더 복잡한 하나에 :

    val x = Map(1 -> ("s" -> 1L)): Any
    failFastCast(Map[Int, (String, String)](), x) // no throw
    

    재귀 적으로 더 이상 유형 매개 변수가 없을 때까지 캐스팅 유지하기 위해 드릴 다운 할 수있는 방법이 있는지 궁금합니다 ...

  2. ==============================

    2.당신은 참으로 정확 - 타입 삭제 수단 당신 예를 들어, 목록 [지능]과 목록 [문자열]을 구별하는 방식으로하지 "캐스트"할 수 있습니다. 당신은 지능과 문자열 사이에 구별 할 수 있음을 의미하지만, 당신은이 같은 방식으로 삭제된다 수행중인 캐스트에 향상시킬 수 있습니다 :

    당신은 참으로 정확 - 타입 삭제 수단 당신 예를 들어, 목록 [지능]과 목록 [문자열]을 구별하는 방식으로하지 "캐스트"할 수 있습니다. 당신은 지능과 문자열 사이에 구별 할 수 있음을 의미하지만, 당신은이 같은 방식으로 삭제된다 수행중인 캐스트에 향상시킬 수 있습니다 :

    def cast[A](a : Any) = a.asInstanceOf[A]
    //... is erased to
    def erasedCast(a : Any) = a.asInstanceOf[Any]
    

    당신은 무엇을 매니페스트를 사용하여 제네릭을 구체화하는 필요

    def cast[A <: AnyRef : Manifest](a : Any) : A 
      = manifest[A].erasure.cast(a).asInstanceOf[A]
    

    최종 캐스트 AnyRef에 삭제되는 동안, 적어도 당신은 최고 수준의 종류가 올바르지 얻을 수있는 올바른 클래스 [_] 예 (manifest.erasure)을 가져야한다. 행동 :

    scala> cast[String]("Hey")
    res0: String = Hey
    
    scala> cast[java.lang.Integer]("Hey")
      java.lang.ClassCastException
        at java.lang.Class.cast(Class.java:2990)
        at .cast(<console>:7)
        at .<init>(<console>:9)
    
    scala> cast[List[String]](List("Hey"))
    res2: List[String] = List(Hey)
    
    scala> cast[List[Int]](List("Hey"))
    res3: List[Int] = List(Hey)
    

    내 조언이 대상이 목록은 정말 여부를 결정하는 중첩 된 반사를 사용하지 않는 것입니다 [지능] :이 일반적으로 가능하지 않다. 무엇을 다음과 반환해야합니다 위해?

    cast[List[Int]](List[AnyVal](1, 2))
    
  3. ==============================

    3.당신은 마일 사빈에서 무형의 Typeable을 사용할 수 있습니다 :

    당신은 마일 사빈에서 무형의 Typeable을 사용할 수 있습니다 :

    형식 매개 변수를 사용하여 주조 입력

    그것은 특정 것들이지만, 많은 경우에 삭제를 처리합니다 :

    scala> import shapeless._; import syntax.typeable._
    import shapeless._
    import syntax.typeable._
    
    scala> val x = List(1, 2, 3)
    x: List[Int] = List(1, 2, 3)
    
    scala> val y = x.cast[List[String]]
    y: Option[List[String]] = None
    

    당신은 그것의 소스를 참조 할 수 있습니다 처리하는 경우 세트를 보려면 :

    https://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/typeable.scala

  4. ==============================

    4.예, 문제 유형의 삭제로 인해 발생합니다. 당신이하려고하면

    예, 문제 유형의 삭제로 인해 발생합니다. 당신이하려고하면

    val x = List(1,2,3)
    val y = castToType[Int](x)
    

    예상대로 예외는, 바로 발생합니다. 배열 [문자열] 또는 배열 [지능]에 캐스팅하려고 할 때 같은가 발생합니다.

    난 당신이 일반적인 형식 변환기를 만들 수 있다고 생각하지 않는 컬렉션과 다른 개체 내부 작품 것이다 종류. 각 객체 유형에 대한 변환기를 만들어야합니다. 예를 들면 :

    def castToType[A](x: List[A]) = x.map(i => i.asInstanceOf[A])
    
  5. ==============================

    5.이 솔루션을 고려 :

    이 솔루션을 고려 :

    trait -->[A, B] {
      def ->(a: A): B
    }
    
    implicit val StringToInt = new -->[String, Int] {
      def ->(a: String): Int = a.toInt
    }
    
    implicit val DateToLong = new -->[java.util.Date, Long] {
      def ->(a: java.util.Date): Long = a.getTime
    }
    
    def cast[A,B](t:A)(implicit ev: A --> B):B= ev.->(t)
    

    장점은 것입니다 :

    이제 당신은 그것을 있도록 사용할 수 있습니다 :

    scala>  cast(new java.util.Date())
    res9: Long = 1361195427192
    
    scala>  cast("123")
    res10: Int = 123
    

    편집하다

    나는 약간의 시간을 보냈다이 고급 코드를 작성했습니다. 첫 번째는 내가 그것을 사용하는 방법을 보여 보자 :

    scala>    "2012-01-24".as[java.util.Date]
    res8: java.util.Date = Tue Jan 24 00:00:00 CET 2012
    
    scala>    "2012".as[Int]
    res9: Int = 2012
    
    scala>    "2012.123".as[Double]
    res12: Double = 2012.123
    
    scala>    "2012".as[Object]   // this is not working, becouse I did not provide caster to Object
    <console>:17: error: could not find implicit value for parameter $greater: -->[String,Object]
    "2012".as[Object]
    ^
    

    꽤 좋은? 스칼라 마법을 참조하십시오 :

    trait -->[A, B] {
      def ->(a: A): B
    }
    
    implicit val StringToInt = new -->[String, Int] {
      def ->(a: String): Int = a.toInt
    }
    
    implicit val StringToDate = new -->[String, java.util.Date] {
      def ->(a: String): java.util.Date = (new java.text.SimpleDateFormat("yyyy-MM-dd")).parse(a)
    }
    
    implicit val StringToDouble = new -->[String, Double] {
      def ->(a: String): Double = a.toDouble
    }
    
    trait AsOps[A] {
      def as[B](implicit > : A --> B): B
    }
    
    implicit def asOps[A](a: A) = new AsOps[A] {
      def as[B](implicit > : A --> B) = > ->(a)
    }
    
  6. from https://stackoverflow.com/questions/6686992/scala-asinstanceof-with-parameterized-types by cc-by-sa and MIT license