Ruby: kind_of? vs. instance_of? vs. is_a?

488

Apa bedanya? Kapan saya harus menggunakan yang mana? Mengapa mereka begitu banyak?

Claudiu
sumber
18
Tentang mengapa keduanya is_a?dan kind_of?ada: Saya kira itu bagian dari filosofi desain Ruby. Python akan mengatakan bahwa seharusnya hanya ada satu cara untuk melakukan sesuatu; Ruby sering memiliki metode sinonim sehingga Anda dapat menggunakan salah satu yang terdengar lebih baik. Ini masalah preferensi. Ini mungkin sebagian karena pengaruh Jepang: Saya diberitahu bahwa mereka akan menggunakan kata yang berbeda untuk nomor yang sama tergantung pada kalimat untuk membuatnya terdengar lebih baik. Matz mungkin telah membawa gagasan itu ke dalam desain bahasanya.
Nathan Long
@ NathanLong Saya tidak berpikir counter Jepang banyak hubungannya dengan itu; semua bahasa memiliki semacam perjanjian dan Anda tidak dapat mengganti satu penghitung untuk waktu yang lain (seperti, Anda tidak dapat menggunakan penghitung silinder untuk objek datar; itu hanya salah). Dan itu lebih berkaitan dengan semantik daripada eufoni.
Casey

Jawaban:

622

kind_of?dan is_a?identik.

instance_of?berbeda dari dua lainnya karena hanya mengembalikan truejika objek adalah turunan dari kelas yang tepat, bukan subkelas.

Contoh:

  • "hello".is_a? Objectdan "hello".kind_of? Objectkembali truekarena "hello"a Stringdan Stringmerupakan subclass dari Object.
  • Namun "hello".instance_of? Objectkembali false.
sepp2k
sumber
77
Terkadang hanya membaca lebih baik. Pikirkan @honda.kind_of? Cardan @person.is_a? Administrator, semua Ruby tentang estetika. Faktanya, perhatikan kesalahan tata bahasa ... dengan dukungan aktif yang dapat Anda tulis:) @person.is_an? Administrator... Itu mungkin sudah menjadi inti Ruby sekarang.
rfunduk
2
heh itu alasan yang menarik. bisakah kau hancurkan ini, kawan? seperti bisakah Anda menimpa kind_of?tetapi tidak is_a??
Claudiu
3
@ thenduks, is_an?tidak di ruby-1.9.2-p0. @Cudiudiu, tidak. is_a?hanyalah alias darikind_of? . Kedua metode memanggil fungsi c yang sama rb_obj_is_kind_of,.
ma11hew28
9
@Matt: Anda dapat mengganti alias tanpa mengabaikan fungsi alias. Jadi ya, Anda dapat mengganti kind_of?tanpa mengesampingkan is_a?.
sepp2k
4
Di mana is_an?metode ActiceSupport ini ?! Itu tidak dalam versi rel saat ini, dan saya tidak dapat menemukan apa pun di google tentang hal itu menjadi usang juga.
Tom Lord
22

Apa bedanya?

Dari dokumentasi:

- ( Boolean )instance_of?(class)
Mengembalikan truejika objadalah turunan dari kelas yang diberikan.

dan:

- ( Boolean ) is_a?(class)
- ( Boolean )kind_of?(class)
Mengembalikan truejika classadalah kelas obj, atau jika classadalah salah satu dari superclasses objatau modul yang disertakan obj.

Jika tidak jelas, alangkah baiknya jika mengetahui apa yang sebenarnya tidak jelas, sehingga dokumentasi dapat ditingkatkan.

Kapan saya harus menggunakan yang mana?

Tidak pernah. Gunakan polimorfisme sebagai gantinya.

Mengapa mereka begitu banyak?

Saya tidak akan menyebut dua "banyak". Ada dua di antara mereka, karena mereka melakukan dua hal yang berbeda.

Jörg W Mittag
sumber
3
Saya pikir kebingungan saya adalah ada 3, dan 2 hanya melakukan hal yang sama dan memiliki nama yang berbeda. Tentang menggunakan polimorfisme - Saya setuju, tetapi perpustakaan standar ruby ​​penuh dengan penggunaan masing-masing
Claudiu
4
Apa yang Anda maksud dengan polimorfisme? Apakah sama dengan mengetik bebek?
Andrew Grimm
2
Ya, mereka sama. Mengetik bebek adalah bentuk polimorfisme.
SpaceGhost
3
Sering kali lebih baik melakukan polimorfisme, ya, tetapi ada kasus perbatasan di mana Anda benar-benar ingin tahu bahwa Anda memiliki kelas tertentu, seperti ketika Anda berurusan dengan file.
Otomatis
6

Lebih seperti Ruby untuk bertanya objek apakah mereka menanggapi metode yang Anda butuhkan atau tidak, gunakan respond_to?. Ini memungkinkan antarmuka minimal dan implementasi pemrograman yang tidak disadari.

Tentu saja hal ini tidak selalu berlaku, sehingga masih ada kemungkinan untuk bertanya tentang pemahaman "tipe" yang lebih konservatif, yaitu kelas atau kelas dasar, menggunakan metode yang Anda tanyakan.

kuonirat
sumber
5
Itu tergantung situasi. Baik Komentar dan Blog dapat merespons ke Created_at. Dalam situasi seperti itu, is_a? IMHO lebih tepat
penkovsky
Itu tidak masuk akal, jika Anda perlu membedakan satu Komentar dan satu objek Blog dari satu sama lain, Anda tidak akan menggunakan Created_at untuk melakukannya. Itu tidak menghalangi bahwa Anda bisa menulis metode yang mengambil objek yang merespons ke create_at. Jika tidak memerlukan hal lain untuk melakukan tugasnya, maka Anda dapat menggunakannya dengan aman di Komentar atau Blog, atau cukup dengan model ActiveRecord lainnya.
Kingdon
3

Saya juga tidak akan memanggil dua banyak ( is_a?dan kind_of?alias dari metode yang sama), tetapi jika Anda ingin melihat lebih banyak kemungkinan, alihkan perhatian Anda ke #classmetode:

A = Class.new
B = Class.new A

a, b = A.new, B.new
b.class < A # true - means that b.class is a subclass of A
a.class < B # false - means that a.class is not a subclass of A
# Another possibility: Use #ancestors
b.class.ancestors.include? A # true - means that b.class has A among its ancestors
a.class.ancestors.include? B # false - means that B is not an ancestor of a.class
Boris Stitnicky
sumber
1
Terima kasih - saya memang bertanya secara umum tentang "informasi jenis run-time apa yang dapat dikumpulkan di Ruby dan bagaimana" - dan ini memberikan banyak contoh
Claudiu