Menentukan jenis objek dalam ruby

365

Saya akan menggunakan python sebagai contoh dari apa yang saya cari (Anda bisa menganggapnya sebagai pseudocode jika Anda tidak tahu Python):

>>> a = 1
>>> type(a)
<type 'int'>

Saya tahu di ruby ​​saya bisa melakukan:

1.9.3p194 :002 > 1.class
 => Fixnum 

Tetapi apakah ini cara yang tepat untuk menentukan jenis objek?

Zippy Zeppoli
sumber
5
@ JörgWMittag Namun AFAICR melakukan `type` dalam Python, meskipun ingatan saya tidak jelas. Anda perlu isinstance atau memeriksa tanggapan. Tetapi hanya mengatakan "NOES !!!" tidak benar-benar membantu, kan? Alih-alih mempertimbangkan untuk mendidik.
Dave Newton
4
@ JörgWMittag Sementara saya simpatik, OP memberikan kode untuk meniru di Ruby. Kecuali Anda benar-benar mendidik OP mengatakan noes tidak membantu, IMO. Dan bahkan jika Anda melakukannya, itu kemungkinan akan menjadi informasi saja, karena OP menentukan apa yang dia inginkan melalui kode.
Dave Newton
5
@ JörgWMittag - di Ruby semuanya adalah Object, jadi tidak ada tipe primitif seperti pada Python (int, long, boolean, dll.) Sebagai hasilnya dalam Ruby, kelas adalah definisi tipe. Ini tidak terbatas pada Ruby, kelas kata dan jenisnya sama dalam beberapa bahasa lain, dan lebih luas lagi dalam teori OOP.
ocodo
6
Karena kita benar-benar berbicara tentang Ruby di sini, Jenis dan Kelas adalah sama, tidak ada perdebatan tentang ini, semua nilai adalah Objek. Jadi bagi siapa pun yang hanya berbicara tentang Ruby, Kelas adalah Jenis. - ref: ruby-lang.org/en/about
ocodo
2
@ JörgWMittag Esai itu cukup informatif sejauh ini, dan saya akan membaca sisanya ketika saya mendapat kesempatan. Secara khusus, Cook tampaknya mengartikulasikan dengan cukup baik (dan dengan pengetahuan latar belakang yang jauh lebih banyak daripada yang saya miliki) mengapa salah mengklaim (seperti yang dilakukan salah satu profesor saya) bahwa Python, Ruby, dan bahasa lain yang diketik secara dinamis "tidak benar - benar objek -berorientasi "(apa yang mungkin dimaksudkannya, tanpa disadari, adalah bahwa mereka tidak berorientasi ADT) Tetapi Ruby tidak diketik secara statis, sehingga tidak memiliki ADT dalam arti yang dideskripsikan oleh Cook, jadi keberatan Anda atas dasar perbedaan itu tidak membantu.
Kyle Strand

Jawaban:

608

Cara yang tepat untuk menentukan "jenis" objek, yang merupakan istilah goyah di dunia Ruby, adalah dengan menelepon object.class.

Karena kelas dapat mewarisi dari kelas lain, jika Anda ingin menentukan apakah suatu objek adalah "dari jenis tertentu" Anda mungkin memanggil object.is_a?(ClassName)untuk melihat apakah objectadalah tipe ClassNameatau berasal dari itu.

Biasanya pengecekan tipe tidak dilakukan di Ruby, tetapi sebaliknya objek dinilai berdasarkan kemampuan mereka untuk merespons metode tertentu, yang biasa disebut " Duck typing ". Dengan kata lain, jika itu menanggapi metode yang Anda inginkan, tidak ada alasan untuk menjadi khusus tentang jenisnya.

Sebagai contoh, object.is_a?(String)terlalu kaku karena kelas lain mungkin mengimplementasikan metode yang mengubahnya menjadi string, atau membuatnya berperilaku identik dengan bagaimana perilaku String. object.respond_to?(:to_s)akan menjadi cara yang lebih baik untuk menguji bahwa objek tersebut melakukan apa yang Anda inginkan.

anak laki-laki
sumber
13
-1. #classtidak tidak kembali jenis objek, ia mengembalikan nya kelas . Nama itu seharusnya merupakan hadiah mati. Kelas dan Jenis adalah dua benar-benar konsep yang berbeda di OO.
Jörg W Mittag
78
@ Jörg W Mittag: Saya tidak setuju. "Kelas" dan "kecepatan prosesor" (untuk mengambil contoh) adalah dua konsep yang sangat berbeda, tetapi "kelas" dan "tipe" adalah konsep yang terkait erat. Sebagai contoh, inilah yang dikatakan artikel Wikipedia tentang Kelas : "Dalam pemrograman berorientasi objek, kelas adalah konstruk yang digunakan untuk mendefinisikan tipe yang berbeda." tadman membantu penanya.
Teemu Leisti
18
@ JörgWMittag Di Ruby hal yang paling dekat dengan typeofdari C, JavaScript dan lainnya class. Tidak ada sistem protokol formal di Ruby seperti di bahasa lain, Objective-C menjadi relatif Smalltalk terdekat dengan itu. Jika Anda mendefinisikan "ketik" sebagai "objek yang merespons serangkaian metode tertentu dengan hasil yang dapat diterima" maka benar-benar tidak ada cara untuk menyatakan itu. Terlalu longgar. Sebagian besar waktu di Ruby ketika merujuk ke jenis objek, dipahami Anda berbicara tentang kelas. Saya memang menggunakan istilah ketik dalam tanda kutip karena alasan itu.
tadman
14
@ Jörg W Mittag: Saya terus menegaskan bahwa "kelas" dan "tipe" jelas bukan konsep yang sepenuhnya berbeda dalam OO, seperti yang ditunjukkan oleh kutipan. (Juga: bagaimana Anda mendeklarasikan variabel di Jawa Dengan memberikan? Baik yang jenis atau kelas variabel, diikuti dengan nama: " int i" atau " Integer j".) Tadman menjawab pertanyaan dengan cara yang tampaknya memenuhi kedua penanya dan khalayak umum, sambil menjelaskan terminologi yang digunakan Ruby. Saya tidak tertarik untuk masuk ke akademik rambut yang terpecah-pecah atas poin-poin penting dari terminologi berorientasi objek, jadi tolong sampaikan kata terakhirnya.
Teemu Leisti
11
@TeemuLeisti Sebagian besar masalah di sini berasal dari kenyataan bahwa semua yang ada di Ruby adalah objek, dan juga memiliki kelas, sedangkan di hampir setiap bahasa ada tipe primitif yang bukan objek dan tidak memiliki kelas, berbeda dengan objek yang melakukannya. Ketika tidak ada yang namanya tipe murni, dan tidak ada cara untuk mendefinisikannya secara formal, artinya menjadi sangat kabur di dunia Ruby. Matz tidak sepenuhnya mengikuti aliran pemikiran tertentu di sini selain miliknya sendiri.
tadman
81

Anda juga dapat mencoba: instance_of?

p 1.instance_of? Fixnum    #=> True
p "1".instance_of? String  #=> True
p [1,2].instance_of? Array #=> True
Arup Rakshit
sumber
44

Seringkali di Ruby, Anda sebenarnya tidak peduli apa kelas objeknya, karena Anda hanya peduli bahwa itu merespons metode tertentu. Ini dikenal sebagai Duck Typing dan Anda akan melihatnya di semua jenis basis kode Ruby.

Jadi dalam banyak (jika tidak sebagian besar) kasus, yang terbaik untuk menggunakan Mengetik Bebek menggunakan #respond_to?(method):

object.respond_to?(:to_i)
Stuart M
sumber
1
titik yang valid. tidak menjawab pertanyaan tetapi menyentuh semangat pertanyaan.
user566245
@ user566245 well itu responds_to? (: the_question), tapi seperti yang Anda katakan itu tidak menjawab pertanyaan, hanya memberikan informasi terkait. Cukup yakin jawaban perlu menjawab pertanyaan itu.
R. Rincón
17

Saya akan mengatakan "Ya". Seperti "Matz" telah mengatakan sesuatu seperti ini dalam salah satu ceramahnya, "Benda Ruby tidak memiliki tipe." Tidak semuanya tetapi bagian yang ia coba sampaikan kepada kami. Mengapa ada orang yang mengatakan "Semuanya adalah Obyek"? Untuk menambahkan dia berkata "Data memiliki Jenis bukan objek".

Jadi kita bisa menikmati ini.

https://www.youtube.com/watch?v=1l3U1X3z0CE

Tapi Ruby tidak terlalu peduli tentang jenis objek hanya kelasnya. Kami menggunakan kelas bukan tipe. Semua data kemudian memiliki kelas.

12345.class

'my string'.class

Mereka mungkin juga memiliki leluhur

Object.ancestors

Mereka juga memiliki kelas meta tetapi saya akan menghemat detail tentang hal itu.

Setelah Anda mengetahui kelasnya maka Anda akan dapat mencari metode apa yang dapat Anda gunakan untuk itu. Di situlah "tipe data" diperlukan. Jika Anda benar-benar ingin masuk ke detail ...

"The Ruby Object Model"

Ini adalah istilah yang digunakan untuk bagaimana Ruby menangani objek. Semuanya internal sehingga Anda tidak benar-benar melihat banyak dari ini, tetapi senang mengetahui. Tapi itu topik lain.

Iya! Kelas adalah tipe data. Objek memiliki kelas dan data memiliki tipe. Jadi jika Anda tahu tentang basis data maka Anda tahu hanya ada satu set tipe yang terbatas.

teks memblokir angka

Douglas G. Allen
sumber
Misalnya,Object.ancestors # => [Object, Kernel, BasicObject]
Dorian