Các loại lớp Ruby và báo cáo trường hợp


134

Sự khác biệt giữa

case item.class
when MyClass
  # do something here
when Array
  # do something different here
when String
  # do a third thing
end

case item.class
when MyClass.class
  # do something here
when Array.class
  # do something different here
when String.class
  # do a third thing
end

Vì một số lý do, cái thứ nhất đôi khi hoạt động và cái thứ hai thì không, và lần khác, cái thứ hai hoạt động và cái thứ nhất thì không. Tại sao? Cái nào là cách "thích hợp" để làm điều đó?


1
Chuỗi là một lớp. Lớp của một lớp là Lớp.
Volte

Lưu ý rằng MyClass === objsử dụng phương thức Module # === để kiểm tra xem có phải objlà một thể hiện của MyClass.
sergio

Câu trả lời:


233

Bạn phải dùng:

case item
when MyClass
...

Tôi có cùng một vấn đề: Làm thế nào để bắt được lớp Errno :: ECONNRESET trong "trường hợp khi nào"?


1
Cảm ơn! Xin lỗi để dupe (hoặc loại dupe), nhưng một số tìm kiếm đã không đưa ra câu hỏi trước đó. Có vẻ như việc sử dụng === bởi câu lệnh tình huống là một vấn đề khá phổ biến, bây giờ tôi thấy đây là vấn đề. Điều này có lẽ nên được chỉ ra thường xuyên hơn trong các hướng dẫn và như vậy (nhưng tôi cá rằng nhiều người viết hướng dẫn cũng không nhận thức được điều này).
Daisy Sophia Hollman

4
Một cảnh báo chưa được đề cập nếu sử dụng ActiveRecord. Phương thức ActiveRecord === trên các so sánh lớp sử dụng .is_a?, Có nghĩa là các lớp con của một lớp sẽ đánh giá là đúng trong câu lệnh tình huống. github.com/rails/rails/blob/ Mạnh
Jeremy Baker

60

Vâng, Nakilon là chính xác, bạn phải biết toán tử baqual === hoạt động như thế nào trên đối tượng được đưa ra trong whenmệnh đề. Trong Ruby

case item
when MyClass
...
when Array
...
when String
...

thực sự là

if MyClass === item
...
elsif Array === item
...
elsif String === item
...

Hiểu trường hợp đó đang gọi một phương thức baqual ( MyClass.===(item)ví dụ) và phương thức đó có thể được xác định để làm bất cứ điều gì bạn muốn, và sau đó bạn có thể sử dụng câu lệnh case với độ chính xác


Nếu tôi có arr = []thì tôi nhận thấy rằng if Array === arrsẽ đánh giá là đúng nhưng if arr === Arraysẽ đánh giá thành sai. Ai đó có thể vui lòng giúp giải thích?
Daniel

4
=== chỉ là một phương thức có thể được định nghĩa để làm bất cứ điều gì mà người thiết kế của một lớp muốn nó làm. Ngoài ra, hãy nhớ rằng a === b thực sự có nghĩa là a. === b, vì vậy nếu bạn chuyển đổi a và b xung quanh, bạn có thể có hành vi khác nhau. Không có gì đảm bảo rằng === là giao hoán. Trong thực tế, Array === Array là sai, nhưng Object === Object là đúng, vì vậy Array đang định nghĩa lại ngữ nghĩa của ===.
Fred


5

Trong Ruby, tên lớp là một hằng số đề cập đến một đối tượng thuộc loại Classmô tả một lớp cụ thể. Điều đó có nghĩa là nói MyClasstrong Ruby tương đương với nói MyClass.classtrong Java.

obj.classlà một đối tượng của kiểu Classmô tả lớp obj. Nếu obj.classMyClass, sau đó objđược tạo ra bằng cách sử dụng MyClass.new(nói đại khái). MyClasslà một đối tượng của kiểu Classmô tả bất kỳ đối tượng nào được tạo bằng cách sử dụng MyClass.new.

MyClass.classlà lớp của MyClassđối tượng (nó là lớp của đối tượng kiểu Classmô tả bất kỳ đối tượng nào được tạo bằng cách sử dụng MyClass.new). Nói cách khác , MyClass.class == Class.


1

Nó phụ thuộc vào bản chất của itembiến của bạn . Nếu nó là một thể hiện của một đối tượng, vd

t = 5

sau đó

t.class == Fixnum

nhưng nếu nó là một lớp trong chính nó, vd

t = Array

sau đó nó sẽ là một Classđối tượng, vì vậy

t.class == Class

EDIT : vui lòng tham khảo Cách bắt Errno :: ECONNRESET trong "trường hợp khi nào"? như Nakilon đã nêu vì câu trả lời của tôi có thể sai.


Trong Ruby, mọi thứ là "một thể hiện của một đối tượng".
Eric Duminil
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.