스칼라 2.7.2부터는 Manifest
자바의 유형 삭제를위한 해결 방법이 있습니다. 그러나 어떻게 Manifest
정확하게 작동하며 왜 / 어떻게 사용해야합니까?
Jorge Ortiz 의 블로그 게시물 Manifests : Reified Types 는 그 중 일부를 설명하지만 컨텍스트 범위 와 함께 사용하는 방법에 대해서는 설명하지 않습니다 .
또한, ClassManifest
차이점은 Manifest
무엇입니까?
유형 삭제와 관련하여 경고가있는 코드 (더 큰 프로그램의 일부, 여기에 쉽게 포함시킬 수 없음)가 있습니다. 매니페스트를 사용하여 이러한 문제를 해결할 수있을 것 같지만 정확히 어떻게 확신 할 수 없습니다.
답변
컴파일러는 JVM 런타임이 쉽게 표현할 수있는 것보다 유형에 대한 자세한 정보를 알고 있습니다. 매니페스트는 컴파일러가 유실 된 유형 정보에 대해 런타임에 코드에 차원 간 메시지를 보내는 방법입니다.
이것은 Kleptonian이 어떻게 화석 기록과 인간의 “정크”DNA에 메시지를 남긴 방식과 비슷합니다. 광속 및 중력 공명 필드의 한계로 인해 직접 통신 할 수 없습니다. 그러나 신호에 맞추는 방법을 알고 있다면 점심 식사를 위해 무엇을 먹을지 또는 어떤 로또를 먹을지 결정하는 것에서 상상할 수없는 방식으로 이익을 얻을 수 있습니다.
매니페스트가 자세한 내용을 알지 못하고 현재보고있는 오류에 도움이 될지 확실하지 않습니다.
매니페스트의 일반적인 용도 중 하나는 정적 유형의 컬렉션에 따라 코드가 다르게 동작하는 것입니다. 예를 들어, List [String]을 다른 유형의 List와 다르게 취급하려면 다음을 수행하십시오.
def foo[T](x: List[T])(implicit m: Manifest[T]) = {
if (m <:< manifest[String])
println("Hey, this list is full of strings")
else
println("Non-stringy list")
}
foo(List("one", "two")) // Hey, this list is full of strings
foo(List(1, 2)) // Non-stringy list
foo(List("one", 2)) // Non-stringy list
이것에 대한 반영 기반 솔루션에는 아마도 목록의 각 요소를 검사하는 것이 필요할 것입니다.
컨텍스트 바운드는 스칼라에서 유형 클래스를 사용하는 데 가장 적합하며 Debasish Ghosh에서 잘 설명합니다.
http://debasishg.blogspot.com/2010/06/scala-implicits-type-classes-here-i.html
컨텍스트 바운드는 메소드 서명을 더 읽기 쉽게 만들 수도 있습니다. 예를 들어, 위의 함수는 다음과 같이 컨텍스트 바운드를 사용하여 다시 작성할 수 있습니다.
def foo[T: Manifest](x: List[T]) = {
if (manifest[T] <:< manifest[String])
println("Hey, this list is full of strings")
else
println("Non-stringy list")
}
답변
의 차이에 관한 아니 완전한 답변 만 Manifest
하고 ClassManifest
, 당신의 예를 찾을 수 있습니다 스칼라 2.8 Array
종이 :
남아있는 유일한 질문은 일반 배열 생성을 구현하는 방법입니다. 자바와는 달리, 스칼라는 인스턴스 생성 새로운 수 있습니다 유형 매개 변수입니다. Java에 균일 한 배열 표현이 없다는 것을 감안할 때 어떻게 구현할 수 있습니까?
Array[T]
T
이를 수행하는 유일한 방법은 유형을 설명하는 추가 런타임 정보가 필요합니다
T
. Scala 2.8에는이를위한 새로운 메커니즘이 있으며이를 매니페스트 라고합니다 . 유형의 객체는 유형에Manifest[T]
대한 완전한 정보를 제공합니다T
.
Manifest
값은 일반적으로 암시 적 매개 변수로 전달됩니다. 그리고 컴파일러는 정적으로 알려진 유형에 대해 구성하는 방법을 알고 있습니다T
.또한 모든 인수 유형을 알 필요없이 유형의 최상위 클래스 만 알고 구성 할 수 있는 약한 형식의 이름 도
ClassManifest
있습니다 .
이 유형의 런타임 정보는 배열 작성에 필요합니다.
예:
ClassManifest[T]
메소드에 암시 적 매개 변수로 를 전달하여이 정보를 제공해야합니다 .
def tabulate[T](len:Int, f:Int=>T)(implicit m:ClassManifest[T]) = {
val xs = new Array[T](len)
for (i <- 0 until len) xs(i) = f(i)
xs
}
속기 형식으로 컨텍스트 바운드 1을 type 매개 변수에
T
대신 사용할 수 있습니다 .
(예를 들어이 SO 질문을 참조하십시오 )
, 기부:
def tabulate[T: ClassManifest](len:Int, f:Int=>T) = {
val xs = new Array[T](len)
for (i <- 0 until len) xs(i) = f(i)
xs
}
Scala 컴파일러는
Int
, 또는String
, 또는 과 같은 형식에서 tabulate를 호출 할 때 테이블 형식에 대한List[T]
암시 적 인수로 전달할 클래스 매니페스트를 만들 수 있습니다.
답변
매니페스트는 JVM에서 실행되도록 유형이 지워진 제네릭 형식 (제네릭을 지원하지 않는)을 수정하기위한 것입니다. 그러나 몇 가지 심각한 문제가있었습니다. 너무 단순해서 스칼라 타입 시스템을 완전히 지원할 수 없었습니다. 따라서 Scala 2.10에서는 더 이상 사용되지 않으며TypeTag
s (기본적으로 Scala 컴파일러 자체가 유형을 나타 내기 위해 사용하므로 Scala 유형을 완전히 지원함) 로 대체되었습니다 . 차이점에 대한 자세한 내용은 다음을 참조하십시오.
다시 말해
언제 필요합니까?
2013-01-04 이전에 Scala 2.10이 출시되었습니다 .
답변
의는 밖으로 CHCK하자 manifest
에 scala
소스 ( Manifest.scala
), 우리는 다음을 참조하십시오
Manifest.scala:
def manifest[T](implicit m: Manifest[T]) = m
따라서 다음 예제 코드와 관련하여
def foo[A](somelist: List[A])(implicit m: Manifest[A]): String = {
if (m <:< manifest[String]) {
"its a string"
} else {
"its not a string"
}
}
우리는 예제 코드에서 제공 한 것을 만족시키는 manifest
function
암시 적 검색을 보았습니다 . 따라서 다음과 같이 전화하면m: Manifest[T]
type parameter
manifest[String]
if (m <:< manifest[String]) {
implicit m
함수에서 정의한 전류 가 유형인지 확인 manifest[String]
하고 유형 manifest
의 함수로 manifest[T]
특정 항목을 검색 manifest[String]
하여 암시 적 여부를 찾습니다.