[SCALA] 가져 오기 TypeTag [A] 클래스에서 [A]
SCALA가져 오기 TypeTag [A] 클래스에서 [A]
나는 오버라이드 (override) 할 필요가 createOld 방법이 있고 나는 그것을 변경할 수 없습니다. 나는 createNew에서 패턴 일치 제공 유형에 TypeTag를 사용하고 싶습니다. 목표는 createOld에서 createNew를 호출하는 방법을 찾는 것입니다. 나의 현재 이해는 이미 TypeTag [A]와 함께 제공되지 않는 경우에 그 컴파일러는 createOld 방법에 대해 충분히 유형 정보가없는 것입니다.
object TypeTagFromClass {
class C1
class C2
// How to get TypeTag[A] needed by createNew?
def createOld[A](c: Class[A]): A = createNew ???
def createNew[A : TypeTag]: A = {
val result = typeOf[A] match {
case a if a =:= typeOf[C1] => new C1()
case a if a =:= typeOf[C2] => new C2()
}
result.asInstanceOf[A]
}
}
해결법
-
==============================
1.나는 확실하지 TypeCreator의이 구현은 절대적으로 맞다면 해요하지만 스칼라 반사를 사용하여 클래스에서 TypeTag을 만들 수 있습니다 :
나는 확실하지 TypeCreator의이 구현은 절대적으로 맞다면 해요하지만 스칼라 반사를 사용하여 클래스에서 TypeTag을 만들 수 있습니다 :
import scala.reflect.runtime.universe._ def createOld[A](c: Class[A]): A = createNew { val mirror = runtimeMirror(c.getClassLoader) // obtain runtime mirror val sym = mirror.staticClass(c.getName) // obtain class symbol for `c` val tpe = sym.selfType // obtain type object for `c` // create a type tag which contains above type object TypeTag(mirror, new TypeCreator { def apply[U <: Universe with Singleton](m: api.Mirror[U]) = if (m eq mirror) tpe.asInstanceOf[U # Type] else throw new IllegalArgumentException(s"Type tag defined in $mirror cannot be migrated to other mirrors.") }) }
당신이 일반적인 매개 변수와 전체 스칼라 유형 정보를 검사 할 필요가없는 경우, 당신은 정말 전체 TypeTag 필요하지 않습니다. 당신은 그것에 대해 ClassTags을 사용할 수 있습니다 :
def createNew[A: ClassTag]: A = { val result = classTag[A].runtimeClass match { case a if a.isAssignableFrom(classOf[C1]) => new C1() case a if a.isAssignableFrom(classOf[C2]) => new C2() } result.asInstanceOf[A] }
또는 어떤 암시 설탕 :
implicit class ClassTagOps[T](val classTag: ClassTag[T]) extends AnyVal { def <<:(other: ClassTag[_]) = classTag.runtimeClass.isAssignableFrom(other.runtimeClass) } def createNew[A: ClassTag]: A = { val result = classTag[A] match { case a if a <<: classTag[C1] => new C1() case a if a <<: classTag[C2] => new C2() } result.asInstanceOf[A] }
당신은 평범한 구식 자바 위해서, newInstance () 메소드를 사용하여 더욱 그를 단순화 할 수 있습니다 :
def createNew[A: ClassTag]: A = classTag[A].runtimeClass.newInstance().asInstanceOf[A]
서로 다른 클래스의 다른 생성자의 매개 변수가 필요하지 않은 경우 이것은 물론에만 작동합니다.
createOld에서이 createNew를 호출하면 TypeTags와 함께보다 훨씬 간단합니다 :
def createOld[A](c: Class[A]): A = createNew(ClassTag[A](c))
-
==============================
2.다음과 같은 작업을 수행 할 (당신의 논리를 사용하여) (당신이 스칼라 형식 시스템의 전원을 사용하지 않는 원인),하지만 당신은 할 수 있습니다 매우 안전하고 정확하지 않습니다 그래서 :
다음과 같은 작업을 수행 할 (당신의 논리를 사용하여) (당신이 스칼라 형식 시스템의 전원을 사용하지 않는 원인),하지만 당신은 할 수 있습니다 매우 안전하고 정확하지 않습니다 그래서 :
def createNew[A](implicit t: TypeTag[A]): A = { val result: Any = t.tpe.toString match { case "C1" => new C1 case "C2" => new C2 } result.asInstanceOf[A] } createNew[C1] //> its all ok createNew[C2] //> its all ok createNew[C3] //> crashes here; lets pretend we got C3 class
createOld와 함께 사용하려면 단지 암시 인수를 전달 :
def createOld[A](c: Class[A])(implicit t: TypeTag[A]): A = createNew[A] createOld[C1] //> its all ok createOld[C2] //> its all ok createOld[C3] //> crashes here; lets pretend we got C3 class
나는 그것을 아주 좋은 아니라는 것을 두 번 당신에게 말할한다고 생각합니다. 우리는 볼품를 사용하여이 코드를 향상시킬 수 있습니다 :
인수로 TypeTag이있는 폴리 함수를 만들 수 있습니다 :
import shapeless._; import scala.reflect.runtime.universe._; def getTypeTag[T](implicit t: TypeTag[T]) = t //> to get TypeTag of a class // here is low prority implicit trait createPolyNewErr extends Poly1 { implicit def newErr[T] = at[T](_ => "Error can not create object of this class") } object createPolyBew extends createPolyNewError { implicit def newC1 = at[TypeTag[C1]](_ => new C1) implicit def newC2 = at[TypeTag[C2]](_ => new C2) } createPolyNew(getTypeTag[C1]) //> success createPolyNew(getTypeTag[C2]) //> success createPolyNew(getTypeTag[C3]) //> String: Error can not create object of this class no crash!
우리는 또한 사용하지 않을 기능 getTypeTag [T] 모든 시간을 위해, 함수를 작성할 수 있습니다 :
def createPoly[T] (implicit t: TypeTag[T], cse: poly.Case[createPolyNew.type, TypeTag[T] :: HNil]) = cse(t) createPoly[C1] //> its all ok createPoly[C2] //> its all ok createPoly[C3] //> String: Error can not create object of this class no crash!
from https://stackoverflow.com/questions/22970209/get-typetaga-from-classa by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] List.filter에 밑줄 (0) | 2019.11.13 |
---|---|
[SCALA] 스파크 데이터 세트 컬럼 내로 ADT / 밀봉 특성 계층을 인코딩 (0) | 2019.11.13 |
[SCALA] 어떻게하면 saveAsTextFile RDD [(문자열, INT)]에 기록 괄호를 제거하려면? (0) | 2019.11.13 |
[SCALA] 스파크 DataFrame에서 === null이 isNull에 차이 (0) | 2019.11.13 |
[SCALA] 어떻게 억제 정보와 SBT의 성공 메시지? (0) | 2019.11.13 |