Determinare il tipo di un oggetto in rubino


365

Userò python come esempio di ciò che sto cercando (puoi pensarlo come pseudocodice se non conosci Python):

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

So che in ruby ​​posso fare:

1.9.3p194 :002 > 1.class
 => Fixnum 

Ma è questo il modo corretto di determinare il tipo di oggetto?


5
@ JörgWMittag Eppure AFAICR è ciò che `type` fa in Python, anche se la mia memoria è confusa. Avresti bisogno isinstance o controlla le risposte. Ma semplicemente dicendo "NOES !!!" non è davvero utile, adesso? Invece considera di essere educativo.
Dave Newton,

4
@ JörgWMittag Mentre sono simpatico, OP ha fornito il codice da imitare in Ruby. A meno che tu non istruisca effettivamente il PO dicendo che i no non sono utili, IMO. E anche se lo facessi, probabilmente sarebbe solo informativo, poiché OP ha definito ciò che voleva attraverso il codice.
Dave Newton,

5
@ JörgWMittag - in Ruby ogni cosa è un oggetto, quindi non ci sono tipi primitivi come in Python (int, long, boolean ecc.) Di conseguenza in Ruby, le classi sono definizioni di tipo. Ciò non si limita nemmeno a Ruby, la classe e il tipo di parole sono sinonimi in molte altre lingue e, più in generale, nella teoria OOP.
ocodo,

6
Dato che stiamo davvero parlando di Ruby qui, Tipi e Classi sono sinonimi, non c'è dibattito su questo, tutti i valori sono Oggetti. Quindi per chiunque parli semplicemente di Ruby, le classi sono tipi. - ref: ruby-lang.org/en/about
ocodo

2
@ JörgWMittag Finora quel saggio è abbastanza informativo e leggerò il resto quando ne avrò la possibilità. In particolare, Cook sembra articolare abbastanza bene (e con una conoscenza di base molto maggiore di me) perché non è corretto affermare (come ha fatto uno dei miei professori) che Python, Ruby e altri linguaggi tipizzati dinamicamente "non sono realmente oggetto orientato "(ciò che probabilmente intendeva, senza rendersene conto, era che non erano orientati all'ADT). Ma Ruby non è tipicamente statico, quindi non ha ADT nel senso che Cook sta descrivendo, quindi le tue obiezioni sulla base di quella distinzione non sono utili.
Kyle Strand

Risposte:


608

Il modo corretto di determinare il "tipo" di un oggetto, che è un termine traballante nel mondo di Ruby, è chiamare object.class.

Poiché le classi possono ereditare da altre classi, se si desidera determinare se un oggetto è "di un tipo particolare", è possibile chiamare object.is_a?(ClassName)per vedere se objectè di tipo ClassNameo derivato da esso.

Normalmente il controllo del tipo non viene eseguito in Ruby, ma gli oggetti vengono valutati in base alla loro capacità di rispondere a metodi particolari, comunemente chiamati " Duck typing ". In altre parole, se risponde ai metodi desiderati, non c'è motivo di essere particolari riguardo al tipo.

Ad esempio, object.is_a?(String)è troppo rigido poiché un'altra classe potrebbe implementare metodi che la convertono in una stringa o far sì che si comporti in modo identico al comportamento di String. object.respond_to?(:to_s)sarebbe un modo migliore per testare che l'oggetto in questione fa quello che vuoi.


13
-1. #classnon non restituire il tipo di oggetto, restituisce la sua classe . Il nome dovrebbe essere un omaggio morto. Classe e tipo sono due concetti completamente diversi in OO.
Jörg W Mittag,

78
@ Jörg W Mittag: non sono d'accordo. "Classe" e "velocità del processore" (per scegliere un esempio) sono due concetti completamente diversi, ma "classe" e "tipo" sono concetti strettamente correlati. Ad esempio, ecco cosa dice l' articolo di Wikipedia su Class : "Nella programmazione orientata agli oggetti, una classe è un costrutto che viene utilizzato per definire un tipo distinto". tadman stava aiutando l'interrogante.
Teemu Leisti,

18
@ JörgWMittag In Ruby la cosa più vicina a typeofda C, JavaScript e altri è class. In Ruby non esiste un sistema di protocollo formale come in altre lingue, con Objective-C il parente di Smalltalk più vicino. Se stai definendo "tipo" come "oggetto che risponde a una particolare serie di metodi con risultati accettabili", non c'è davvero modo di affermarlo. È troppo sciolto. Il più delle volte in Ruby quando ci si riferisce al tipo di un oggetto, si capisce che stai parlando della classe. Ho usato il termine tra virgolette proprio per questo motivo.
Tadman,

14
@ Jörg W Mittag: continuo ad affermare che "classe" e "tipo" non sono certamente concetti completamente diversi in OO, come dimostrato dalla citazione. (Anche: come si fa a dichiarare una variabile in Java Dando? Sia il tipo o la classe della variabile, seguito dal suo nome: " int i" o " Integer j".) Tadman rispose alla domanda in un modo che sembrava soddisfare sia l'interrogante e il pubblico in generale, pur chiarendo la terminologia usata da Ruby. Non mi interessa interessarmi della scissione accademica sui punti più fini della terminologia orientata agli oggetti, quindi per favore, abbi l'ultima parola.
Teemu Leisti,

11
@TeemuLeisti La maggior parte dei problemi qui deriva dal fatto che tutto in Ruby è un oggetto, e quindi ha una classe, mentre praticamente in ogni altro linguaggio ci sono tipi primitivi che non sono oggetti e non hanno classe, contrariamente agli oggetti che lo fanno. Quando non esiste un tipo puro, né un modo per definirlo formalmente, il significato diventa particolarmente confuso nel mondo Ruby. Matz non sta aderendo rigorosamente a nessuna particolare scuola di pensiero qui diversa dalla sua.
Tadman,

81

potresti anche provare: instance_of?

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

44

Spesso in Ruby, in realtà non ti importa quale sia la classe dell'oggetto, di per sé, ti importa solo che risponda a un certo metodo. Questo è noto come Duck Typing e lo vedrai in tutti i tipi di codebase di Ruby.

Quindi in molti casi (se non nella maggior parte), è meglio usare Duck Typing usando #respond_to?(method):

object.respond_to?(:to_i)

1
punto valido. non risponde alla domanda ma colpisce lo spirito della domanda.
user566245

@ user566245 bene responds_to? (: the_question), ma come hai detto non risponde alla domanda, fornisce solo informazioni correlate. Le risposte abbastanza sicure devono rispondere alla domanda.
R. Rincón,

17

Direi di si". Dato che "Matz" aveva detto qualcosa del genere in uno dei suoi discorsi, "Gli oggetti di Ruby non hanno tipi". Non tutto ma la parte che sta cercando di farci conoscere. Perché qualcuno avrebbe detto "Tutto è un oggetto" allora? Per aggiungere ha detto "I dati hanno tipi non oggetti".

Quindi potremmo divertirci.

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

Ma a Ruby non interessa molto del tipo di oggetto solo la classe. Usiamo classi non tipi. Tutti i dati hanno quindi una classe.

12345.class

'my string'.class

Possono anche avere antenati

Object.ancestors

Hanno anche meta-classi ma ti salverò i dettagli su questo.

Una volta che conosci la classe, sarai in grado di cercare quali metodi puoi usare per essa. Ecco dove è necessario il "tipo di dati". Se vuoi davvero entrare nei dettagli, cerca ...

"Il modello di oggetti Ruby"

Questo è il termine usato per come Ruby gestisce gli oggetti. È tutto interno, quindi non ne vedi molto, ma è bello saperlo. Ma questo è un altro argomento.

Sì! La classe è il tipo di dati. Gli oggetti hanno classi e i dati hanno tipi. Quindi, se conosci le basi di dati, sai che ci sono solo un insieme finito di tipi.

numeri di blocchi di testo


Ad esempio,Object.ancestors # => [Object, Kernel, BasicObject]
Dorian
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.