Jenis kelas dan pernyataan kasus Ruby


135

Apa perbedaan antara

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

dan

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

Untuk beberapa alasan, yang pertama kadang-kadang bekerja dan yang kedua tidak, dan kali lain, yang kedua bekerja dan yang pertama tidak. Mengapa? Mana yang merupakan cara yang "tepat" untuk melakukannya?


1
String adalah kelas. Kelas suatu kelas adalah Kelas.
Volte

Catatan yang MyClass === objmenggunakan metode Module # === untuk memeriksa apakah objmerupakan instance dari MyClass.
sergio

Jawaban:


234

Anda harus menggunakan:

case item
when MyClass
...

Saya memiliki masalah yang sama: Bagaimana cara menangkap kelas Errno :: ECONNRESET di "case when"?


1
Terima kasih! Maaf untuk menipu (atau semacam penipuan), tetapi beberapa pencarian tidak muncul pertanyaan sebelumnya. Tampaknya penggunaan === oleh pernyataan kasus cukup masalah umum, sekarang saya melihat ini masalahnya. Ini mungkin harus lebih sering ditunjukkan dalam tutorial dan semacamnya (tapi saya yakin banyak penulis tutorial juga tidak mengetahui hal ini).
Daisy Sophia Hollman

4
Peringatan yang belum disebutkan jika menggunakan ActiveRecord. Metode ActiveRecord === pada perbandingan kelas menggunakan .is_a ?, yang berarti bahwa subkelas kelas akan mengevaluasi true dalam pernyataan kasus. github.com/rails/rails/blob/…
Jeremy Baker

61

Ya, Nakilon benar, Anda harus tahu bagaimana operator threequal === bekerja pada objek yang diberikan dalam whenklausa. Di Ruby

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

benar-benar

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

Memahami bahwa case memanggil metode threequal ( MyClass.===(item)misalnya), dan metode itu dapat didefinisikan untuk melakukan apa pun yang Anda inginkan, dan kemudian Anda dapat menggunakan pernyataan case dengan precisionw


Jika sudah arr = []maka saya perhatikan bahwa if Array === arrakan mengevaluasi ke true tetapi if arr === Arrayakan mengevaluasi ke false. Bisakah seseorang tolong bantu menjelaskan?
Daniel

4
=== hanyalah sebuah metode yang dapat didefinisikan untuk melakukan apa pun yang diinginkan oleh perancang kelas. Ingat juga, bahwa a === b benar-benar berarti a. === b, jadi jika Anda beralih a dan b di sekitar, Anda bisa mendapatkan perilaku yang berbeda. Tidak ada jaminan bahwa === bersifat komutatif. Faktanya, Array === Array itu salah, tetapi Object === Object itu benar, jadi Array mendefinisikan ulang semantik dari ===.
Fred


5

Di Ruby, nama kelas adalah konstanta yang merujuk ke objek tipe Classyang menggambarkan kelas tertentu. Itu berarti mengatakan MyClassdi Ruby sama dengan mengatakan MyClass.classdi Java.

obj.classadalah objek bertipe Classmenggambarkan kelas obj. Jika obj.classini MyClass, maka objdibuat menggunakan MyClass.new(berbicara kasar). MyClassadalah objek bertipe Classyang menjelaskan objek apa pun yang dibuat menggunakan MyClass.new.

MyClass.classadalah kelas dari MyClassobjek (itu adalah kelas dari objek tipe Classyang menggambarkan objek yang dibuat menggunakan MyClass.new). Dengan kata lain MyClass.class == Class,.


1

Itu tergantung pada sifat itemvariabel Anda . Jika itu adalah instance dari objek, misalnya

t = 5

kemudian

t.class == Fixnum

tetapi jika itu adalah kelas itu sendiri misalnya

t = Array

maka itu akan menjadi Classobjek, jadi

t.class == Class

EDIT : silakan merujuk ke Cara menangkap kelas Errno :: ECONNRESET di "case when"? seperti yang dinyatakan oleh Nakilon karena jawaban saya bisa salah.


Di Ruby, semuanya adalah "turunan dari suatu objek".
Eric Duminil
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.