2010-01-08 5 views
6

Tôi không hiểu tại sao trường hợp sau không khớp. Null nên là một thể hiện của Any, nhưng nó không khớp. Ai đó có thể giải thích những gì đang xảy ra?tuple khớp với null

val x = (2, null) 
x match { 
    case (i:Int, v:Any) => println("got tuple %s: %s".format(i, v)) 
    case _ => println("catch all") 
} 

prints catch all 

Cảm ơn.

Trả lời

9

Điều này chính xác như được chỉ định.

Type patterns consist of types, type variables, and wildcards. 
A type pattern T is of one of the following forms: 

* A reference to a class C, p.C, or T#C. 
This type pattern matches any non-null instance of the given class. 

Thật thú vị khi có nhiều sự liên quan được gán cho null là thành viên của Bất kỳ. Nó là một thành viên của mọi loại nhưng AnyVal và Nothing.

+0

Tôi giả sử một/động lực cho sự lựa chọn này là nó phù hợp với hành vi của bytecode "instanceof" trên JVM. –

+0

Điều đó, và để trống thông qua hoàn toàn sẽ hút. Bạn phải có một sự khoan dung vô nghĩa khiêu dâm để đi tìm động lực! – extempore

+0

"Khiêu dâm không khoan dung" hay không, có một lập luận rằng ý nghĩa tự nhiên và đơn giản nhất cho một kiểu mẫu "x: T" là khớp với bất kỳ thành viên nào của loại T. Ví dụ, nó sẽ tránh những sai phạm như "val x: Any = null "- tốt, nhưng" val (x: Bất kỳ, y: Bất kỳ) = (null, null) "- MatchError. Điều đó "hoàn toàn hút" quá. Tôi không nói rằng Scala đã lựa chọn sai, cũng không phải là nó đặc biệt quan trọng cho rằng Scala thành ngữ tránh sử dụng null. –

1

Tôi chỉ đoán ở đây vì tôi không có chuyên gia scala nhưng theo số documentation cho lớp Bất kỳ trong scala Tôi nghĩ rằng vì null không phải là một đối tượng, nó không lấy được từ Bất kỳ và như như vậy không khớp với trường hợp được liệt kê đầu tiên.

Thêm mẫu mã bên dưới. Nó in "cái gì khác" khi chạy.

val x = (2, null) 
x match { 
    case (i:Int, v:Any) => println("got tuple %s: %s".format(i, v)) 
    case (i:Int, null) => println("something else %s".format(i)) 
    case _ => println("catch all") 
} 

Sau khi nghiên cứu thêm, có vẻ như null phải khớp với bất kỳ ý nghĩa nào documentation nói rằng nó mở rộng AnyRef mở rộng Bất kỳ.

EDIT: Giống như mọi người khác đã nói. Trường hợp đầu tiên không phù hợp với mục đích. Nó được chỉ định trong tài liệu.

+0

'null' là trường hợp đơn lẻ của lớp' Null'. –

+0

Điều đó có ý nghĩa. Tài liệu cho null (http://www.scala-lang.org/docu/files/api/scala/Null.html) cho biết nó mở rộng AnyRef mở rộng Any, do đó, có vẻ như nó phải khớp với trường hợp (i: Int, v: Bất kỳ). –

3

Đó là theo quy định (Scala Reference 2.7, phần 8.2):

Một tham chiếu đến một lớp C, p.C, hoặc T # C. Kiểu mẫu này khớp với bất kỳ cá thể không rỗng nào của lớp đã cho. Lưu ý rằng tiền tố của lớp học, nếu nó được cung cấp, có liên quan để xác định các phiên bản lớp. Đối với ví dụ , mẫu p.C chỉ khớp với trường hợp của các lớp C là được tạo bằng đường dẫn p làm tiền tố.

6

Bạn đã thử trình giữ chỗ v cho mọi thứ?

val x = (2, null) 
x match { 
    case (i:Int, v) => println("got tuple %s: %s".format(i, v)) 
    case _ => println("catch all") 
}