2011-08-23 28 views
17

Làm cách nào để sử dụng câu lệnh "đối sánh" để xác định giá trị của biến lớp? Sau đây là không hợp lệ, và tôi không thể tìm thấy một biến thể chấp nhận được - không phải là if ... else if ... else ...Làm cách nào để tôi có thể đối sánh các lớp học trong một tuyên bố "phù hợp" Scala?

val c: Class[_] = classOf[Int] 
val what = c match { case classOf[Int] => "int!"; case classOf[Float] => "float!" } 

Trình biên dịch phàn nàn: error: not found: type classOf

Và tất nhiên , tôi không thể sử dụng Class[Int] vì đó loại thông tin bị xóa: biến thể

c match { case Class[Int] => "int!"; case Class[Float] => "float!" } 
error: type Class of type Class does not take type parameters. 

tôi cũng đã cố gắng như Int.class, tất cả không có kết quả. (Và tôi không thực sự muốn chuyển đổi thành chuỗi: Tôi cảm thấy điều quan trọng là phải có trình biên dịch bắt các lớp đã được đổi tên/di chuyển.)

Tôi có bị dày đặc, hoặc tôi tình cờ gặp một điểm mù Scala?

+1

Vâng, câu trả lời dưới đây là chính xác (và cảm ơn cho câu trả lời!) nhưng nó ngày càng xuất hiện * là * một loại lỗ xấu xí ở Scala. Các lớp là những người độc thân, vì vậy không có lý do gì bạn nên gán chúng cho các biến để phù hợp với chúng một cách hiệu quả - cũng không phải sử dụng một loạt các ifs, được viết như các bảo vệ hoặc các câu lệnh riêng biệt. Nhưng rõ ràng là vậy. – Tim

Trả lời

18

Bạn có thể phù hợp với các giá trị lớp nếu bạn tạo một định danh ổn định (ví dụ. Một val) cho họ,

scala> val c: Class[_] = classOf[Int] 
c: Class[_] = int 

scala> val ClassOfInt = classOf[Int] 
ClassOfInt: java.lang.Class[Int] = int 

scala> val ClassOfFloat = classOf[Float] 
ClassOfFloat: java.lang.Class[Float] = float 

scala> val what = c match { 
    |  case ClassOfInt => "int!" 
    |  case ClassOfFloat => "float!" 
    | } 
what: String = int! 

Lưu ý rằng bạn không thể phù hợp trên loại (tức. Class [Int]) vì tẩy xoá có nghĩa là loại instantiations khác nhau của class [T] không thể phân biệt khi chạy ... do đó các cảnh báo dưới đây

scala> val what = c match { 
    |  case _: Class[Int] => "int!" 
    |  case _: Class[Float] => "float!" 
    | } 
warning: there were 2 unchecked warnings; re-run with -unchecked for details 
what: java.lang.String = int! 
+1

Số nhận dạng ổn định - vâng, tôi sợ điều đó. Hiếm. "Lưu ý rằng bạn không thể khớp trên loại (ví dụ: Class [Int])" - có, được ghi chú trong câu hỏi. Cảm ơn bạn mặc dù! – Tim

+0

(Tôi cũng nên lưu ý rằng câu trả lời này có khả năng hiệu quả hơn so với câu dưới đây, vì vậy nó gần gũi hơn với những gì tôi đang tìm kiếm. Cảm ơn một lần nữa!) – Tim

+1

Lưu ý quan trọng: tên của 'val' phải bắt đầu bằng chữ hoa. – vpipkt

26

Trường hợp so sánh tiết hoạt động:

val what = c match { 
    case q if q == classOf[Int] => "int!" 
    case q if q == classOf[Float] => "float!" 
} 

Tất nhiên, là một dạng chữ thường, classOf không nên làm việc trực tiếp trong một tuyên bố trường hợp nào. Tuy nhiên, cũng không được thoát

case `classOf`[Int] 

làm việc trong trường hợp này, vì vậy bạn sẽ phải đi với if -guard.

+0

Có, công cụ bảo vệ nếu ... chuyển đổi câu lệnh 'case' thành tập hợp các câu lệnh' if/else'. Xấu xí, nhưng khá chính xác. Cảm ơn bạn! – Tim

+0

giải pháp thông minh cho câu hỏi này – javadba

0

tôi gặp phải cùng một vấn đề và đặt lớp trong một 'định danh ổn định' là không phải là thực tế . Tôi tìm thấy điều tốt nhất tiếp theo là để có gọn gàng 'khác nếu' báo cáo.

Sử dụng phương pháp này:

private def is[T <: AnyRef : Manifest](implicit cls: Class[_]) = 
    cls == manifest[T].runtimeClass 

tôi có thể viết:

implicit val arg = cls 
    if (is[ClassA]) ... 
    else if (is[ClassB]) ... 
    ... 
    else throw new IllegalArgumentException("Unknown class: " + cls) 
+0

Ha ha. Tôi chỉ tìm thấy câu trả lời của riêng mình một lần nữa nhưng tôi không thể bỏ phiếu cho nó. –

0

Xem xét thừa kế:

val what = c match { 
    case q if classOf[Int].isAssignableFrom(q) => "int!" 
    case q if classOf[Float].isAssignableFrom(q) => "float!" 
} 
Các vấn đề liên quan