Bạn không thể so sánh các loại trực tiếp, bởi vì không có gì để so sánh (khi chạy, do erasure). Bạn có thể làm việc trên một đại diện của lớp học của bạn:
trait TraitA { }
trait TraitB { }
class ClassA extends TraitA { }
class ClassB extends TraitB { }
def myFunc[T](clazz: Class[T]) = {
if (classOf[TraitA] isAssignableFrom clazz) println("A")
else if (classOf[TraitB] isAssignableFrom clazz) println("B")
else println("?")
}
scala> myFunc(classOf[ClassA])
A
scala> myFunc(classOf[String])
?
hoặc bạn có thể mô hình phù hợp trên trường hợp của lớp:
def myFunc2[T](t: T) = t match {
case _: TraitA => println("A")
case _: TraitB => println("B")
case _ => println("?")
}
scala> myFunc2(new ClassA)
A
scala> myFunc2(Some(5))
?
Bạn cũng có thể sử dụng phương pháp tiếp cận đầu tiên trong một cách cú pháp ít gây khó chịu qua lớp biểu hiện:
def myFunc3[T](implicit mf: ClassManifest[T]) = {
val clazz = mf.erasure
if (classOf[TraitA] isAssignableFrom clazz) println("A")
else if (classOf[TraitB] isAssignableFrom clazz) println("B")
else println("?")
}
scala> myFunc3[ClassA]
A
scala> myFunc3[String]
?
và bạn có thể chọn các loại khác nhau của văn cũng nếu if/else trở thành wieldy:
object MyFunc {
val dispatch = Map(
classOf[TraitA] -> (() => println("A")),
classOf[TraitB] -> (() => println("B"))
)
val default =() => println("?")
def apply[T](implicit mf: ClassManifest[T]) =
dispatch.find(_._1 isAssignableFrom mf.erasure).map(_._2).getOrElse(default)()
}
scala> MyFunc[ClassA]
A
scala> MyFunc[String]
?
Lưu ý rằng bất kỳ mã chung nào mà bạn sử dụng mã này sẽ cần phải có sẵn tệp kê khai lớp (dưới dạng tham số ẩn hoặc viết tắt, [T: ClassManifest]
.
Nguồn
2011-03-30 15:05:22
Tôi thực sự tìm thấy 2 cách hoạt động tốt trong trường hợp của tôi: 1) classOf [TraitA] isAssignableTừ clazz như bạn đã đề xuất 2) if (mf <:
codefly
+1: lúc đầu tôi thấy khó chịu với cả câu trả lời và Scala ("Bạn không thể so sánh trực tiếp các loại, vì không có ** gì cả * * có để so sánh "... Có ** loại **, và một loại chắc chắn là một cái gì đó. Bạn nên viết" không có bất kỳ giá trị * * "IMHO). Nhưng sau đó bạn giải thích về các biểu hiện lớp học, và điều đó xảy ra tại chỗ. Cảm ơn! – rsenna
@rsenna - Bởi "không có bất cứ điều gì" Tôi có nghĩa là không có bất cứ điều gì có _at runtime_ vì 'T' chỉ nói với trình biên dịch như thế nào nó nên giữ cho các loại của bạn ngay tại thời gian biên dịch. Vì vậy, thực sự ... một loại chung là, trong thời gian chạy, không có gì. Nó đi rồi. ("Loại tẩy xoá.") Tệp kê khai cung cấp một cách để cung cấp thông tin biên dịch thời gian đó khi chạy. ('ClassTag' hoặc' TypeTag' là cách mới để làm điều đó trong 2,10, mặc dù cách cũ vẫn hoạt động.) Dù sao, vui mừng bạn thấy nó hữu ích ngay cả khi cách nói của tôi không phải là rất lịch sự! –