Nó được một lúc kể từ khi tôi đào thông qua các mã nguồn cho Scala trong một nhiệm vụ để trả lời cùng một câu hỏi ... nhưng câu trả lời ngắn, khi tôi gọi lại -
Manifest là một cheat code để cho phép trình biên dịch để nhận được xung quanh loại tẩy xoá (nó không được sử dụng trong thời gian chạy). Nó gây ra nhiều đường dẫn mã được tạo ra tại thời gian biên dịch cho các kiểu đầu vào có thể khớp với tệp kê khai.
Tệp kê khai được giải quyết hoàn toàn, nhưng nếu có bất kỳ sự mơ hồ nào tại thời gian biên dịch về loại Manifest thì trình biên dịch sẽ dừng lại.
Với bản sao của Manifest
bạn có một vài thứ có sẵn. Những điều chính bạn thường muốn có thể là từ java.lang.Class
đã được xoá hoàn toàn qua erasure
:
class BoundedManifest[T <: Any : Manifest](value: T) {
val m = manifest[T]
m.erasure.toString match {
case "class java.lang.String" => println("String")
case "double" | "int" => println("Numeric value.")
case x => println("WTF is a '%s'?".format(x))
}
}
class ImplicitManifest[T <: Any](value: T)(implicit m: Manifest[T]) {
m.erasure.toString match {
case "class java.lang.String" => println("String")
case "double" | "int" => println("Numeric value.")
case x => println("WTF is a '%s'?".format(x))
}
}
new BoundedManifest("Foo Bar!")
// String
new BoundedManifest(5)
// Numeric value.
new BoundedManifest(5.2)
// Numeric value.
new BoundedManifest(BigDecimal("8.62234525"))
// WTF is a 'class scala.math.BigDecimal'?
new ImplicitManifest("Foo Bar!")
// String
new ImplicitManifest(5)
// Numeric value.
new ImplicitManifest(5.2)
// Numeric value.
new ImplicitManifest(BigDecimal("8.62234525"))
// WTF is a 'class scala.math.BigDecimal'?
Đây là một ví dụ khá lung lay nhưng cho thấy những gì đang xảy ra. Tôi chạy nó cho đầu ra cũng như FWIW trên Scala 2.8.
Ranh giới [T ... : Manifest]
là mới trong Scala 2.8 ... bạn thường phải nắm rõ tệp kê khai như được hiển thị trong ImplicitManifest
. Bạn không thực sự GET một bản sao của Manifest. Nhưng bạn có thể tìm nạp một mã bên trong mã của mình bằng cách nói val m = manifest[T]
... manifest[_]
được xác định trên Predef
và có thể sẽ tìm thấy loại tệp kê khai phù hợp bên trong một khối liên kết.
Hai mục chính khác mà bạn nhận được từ một số Manifest
là <:<
và >:>
kiểm tra loại phụ/siêu mẫu của một tệp kê khai so với loại khác. Nếu tôi nhớ lại một cách chính xác thì việc triển khai VERY vô cùng khôn ngoan và không phải lúc nào cũng phù hợp nhưng tôi có một nhóm mã sản xuất sử dụng chúng để kiểm tra một vài đầu vào có thể bị xóa.Một ví dụ đơn giản kiểm tra đối với biểu hiện khác:
class BoundedManifestCheck[T <: Any : Manifest](value: T) {
val m = manifest[T]
if (m <:< manifest[AnyVal]) {
println("AnyVal (primitive)")
} else if (m <:< manifest[AnyRef]) {
println("AnyRef")
} else {
println("Not sure what the base type of manifest '%s' is.".format(m.erasure))
}
}
new BoundedManifestCheck("Foo Bar!")
// AnyRef
new BoundedManifestCheck(5)
// AnyVal (primitive)
new BoundedManifestCheck(5.2)
// AnyVal (primitive)
new BoundedManifestCheck(BigDecimal("8.62234525"))
// AnyRef
Jorge Ortiz có một bài đăng blog tuyệt vời (mặc dù cũ) về vấn đề này: http://www.scala-blogs.org/2008/10/manifests-reified-types.html
EDIT:
Bạn thực sự có thể nhìn thấy những gì Scala làm bằng cách yêu cầu nó in ra các kết quả của giai đoạn biên dịch xóa.
Chạy, trên ví dụ cuối cùng của tôi ở trên scala -Xprint:erasure test.scala
tạo ra kết quả sau: [? Là gì Manifest tại Scala và khi nào bạn cần nó]
final class Main extends java.lang.Object with ScalaObject {
def this(): object Main = {
Main.super.this();
()
};
def main(argv: Array[java.lang.String]): Unit = {
val args: Array[java.lang.String] = argv;
{
final class $anon extends java.lang.Object {
def this(): anonymous class $anon = {
$anon.super.this();
()
};
class BoundedManifestCheck extends java.lang.Object with ScalaObject {
<paramaccessor> private[this] val value: java.lang.Object = _;
implicit <paramaccessor> private[this] val evidence$1: scala.reflect.Manifest = _;
def this($outer: anonymous class $anon, value: java.lang.Object, evidence$1: scala.reflect.Manifest): BoundedManifestCheck = {
BoundedManifestCheck.super.this();
()
};
private[this] val m: scala.reflect.Manifest = scala.this.Predef.manifest(BoundedManifestCheck.this.evidence$1);
<stable> <accessor> def m(): scala.reflect.Manifest = BoundedManifestCheck.this.m;
if (BoundedManifestCheck.this.m().<:<(scala.this.Predef.manifest(reflect.this.Manifest.AnyVal())))
scala.this.Predef.println("AnyVal (primitive)")
else
if (BoundedManifestCheck.this.m().<:<(scala.this.Predef.manifest(reflect.this.Manifest.Object())))
scala.this.Predef.println("AnyRef")
else
scala.this.Predef.println(scala.this.Predef.augmentString("Not sure what the base type of manifest '%s' is.").format(scala.this.Predef.genericWrapArray(Array[java.lang.Object]{BoundedManifestCheck.this.m().erasure()})));
protected <synthetic> <paramaccessor> val $outer: anonymous class $anon = _;
<synthetic> <stable> def Main$$anon$BoundedManifestCheck$$$outer(): anonymous class $anon = BoundedManifestCheck.this.$outer
};
new BoundedManifestCheck($anon.this, "Foo Bar!", reflect.this.Manifest.classType(classOf[java.lang.String]));
new BoundedManifestCheck($anon.this, scala.Int.box(5), reflect.this.Manifest.Int());
new BoundedManifestCheck($anon.this, scala.Double.box(5.2), reflect.this.Manifest.Double());
new BoundedManifestCheck($anon.this, scala.package.BigDecimal().apply("8.62234525"), reflect.this.Manifest.classType(classOf[scala.math.BigDecimal]))
};
{
new anonymous class $anon();
()
}
}
}
}
thể trùng lặp của (http://stackoverflow.com/ question/3213510/what-is-a-manifest-in-scala-và-khi-do-bạn-cần-nó) –
Tôi không chắc chắn rằng những câu trả lời thực sự trả lời nó hoạt động như thế nào, mặc dù? Ít nhất nó có thể rõ ràng hơn. Có phải điểm mà trình biên dịch thêm một đối số bổ sung vào các phương thức/hàm để giữ lớp bê tông cho tham số chung không? Và toán tử <:
djc
Hãy xem tại đây: http://debasishg.blogspot.com/2010/08/using-generalized-type-constraints-how.html –