Periksa apakah suatu variabel adalah string di Ruby

124

Apakah ada yang lebih idiomatis dari yang berikut ini?

foo.class == String
davidchambers.dll
sumber

Jawaban:

205

Saya pikir Anda sedang mencari instance_of?. is_a?dan kind_of?akan mengembalikan true untuk instance dari kelas turunan.

class X < String
end

foo = X.new

foo.is_a? String         # true
foo.kind_of? String      # true
foo.instance_of? String  # false
foo.instance_of? X       # true
Candide
sumber
9
Tanpa mengetahui maksud pertanyaan tersebut, menurut saya untuk sebagian besar situasi pemrograman dunia nyata, is_a?sebenarnya adalah idiom yang lebih tepat untuk digunakan (dan seringkali cek mengetik bebek seperti yang disebutkan Andrew Grimm bahkan lebih baik). Perbandingan kelas yang ketat biasanya merupakan bau kode. en.wikipedia.org/wiki/Liskov_substitution_principle
mahemoff
Cepat singkirkan: jika Anda menggunakan ini dalam logika kondisional, Anda perlu menggunakan tanda kurung; misalnya, if foo.is_a? (String) && ...
dan
Seperti yang diharapkan, pendekatan ini akan bekerja tidak hanya dengan String, tetapi juga dengan Integerdan Float. Apakah itu juga berhasil Decimal? (penerjemah teks luhur menyoroti sintaks berbeda Decimalyang membuat saya curiga)
stevec
29

Pendekatan yang lebih mengetik bebek bisa dikatakan

foo.respond_to?(:to_str)

to_str menunjukkan bahwa kelas objek mungkin bukan turunan sebenarnya dari String, tetapi objek itu sendiri sangat mirip string (stringy?).

Andrew Grimm
sumber
Keren. Dalam hal ini saya kebetulan tahu bahwa foobaik akan true, falseatau vanili string, tapi baik itu untuk belajar solusi yang lebih umum.
davidchambers
gabungkan ini dengan panggilan to_s setelah memeriksa apakah objek meresponnya, dan Anda mendapatkan sebuah string!
seanmakesgames
1
@seanmakesgames Apakah maksud Anda to_str, atau to_s? Keduanya sedikit berbeda.
Andrew Grimm
stackoverflow.com/questions/11182052/… Re: komentar Andrew.
seanmakesgames
23

Anda dapat melakukan:

foo.instance_of?(String)

Dan yang lebih umum:

foo.kind_of?(String)
Federico Builes
sumber
4
Apa yang membuatnya kind_oflebih umum? Mereka tampaknya identik: is_a.
davidchambers
2
@Davidchambers kau benar, 'kind_of?' adalah sinonim untuk 'is_a?'.
steenslag
@davidchambers: Anda benar, maksud saya, instance_of?bukan is_a?.
Federico Builes
7
foo.instance_of? String

atau

foo.kind_of? String 

jika Anda Anda hanya peduli jika itu diturunkan dari Stringsuatu tempat ke atas rantai warisannya

Matthew
sumber
4

Selain jawaban lainnya, Kelas mendefinisikan metode === untuk menguji apakah suatu objek adalah turunan dari kelas itu.

  • o.class kelas o.
  • o.instance_of? c menentukan apakah o.class == c
  • o.is_a? c Apakah o turunan dari c atau salah satu subkelasnya?
  • baiklah? c sinonim untuk * is_a? *
  • c === o untuk kelas atau modul, tentukan apakah * o.is_a? c * ( String === "s" mengembalikan nilai true)
steenslag.dll
sumber
-1

Menurut saya cara yang lebih baik adalah dengan membuat beberapa metode predikat. Ini juga akan menyimpan "Titik Kontrol Tunggal" Anda.

class Object
 def is_string?
   false
 end
end

class String
 def is_string?
   true
 end
end

print "test".is_string? #=> true
print 1.is_string?      #=> false

Cara mengetik lebih bebek;)

schlegel11.dll
sumber
2
ada apa dengan "string".is_a?(String). Sepertinya Anda menciptakan kembali kemudi. Ada juga class, instance_of, kind_of, dll ... Bad ide untuk monyet patch Objectkelas, belum lagi itu perlu.
Mohamad
Saya sangat setuju dengan Anda :) Jika fokus Anda hanya pada tipe primitif dan Anda tahu bahwa persyaratan proyek Anda yang terkait dengan tipe primitif tidak akan pernah berubah (ok biasanya terjadi;)) Anda baik-baik saja. Tetapi dalam kasus di mana persyaratan berubah lebih baik untuk memiliki "Titik Kontrol Tunggal". Misalnya di lingkungan proyek Anda, Anda memiliki banyak pemeriksaan awal (1000 dan lebih tinggi). pre_check("test".is_string?) Sekarang kebutuhan proyek Anda akan berubah dan setiap String dengan tiga karakter atau lebih tidak lagi didefinisikan sebagai String (saya tahu ini tidak biasa;)) Sekarang Anda dapat mengubah metode Anda sendiri dengan mudah.
schlegel11