Ruby: kind_of? vs. istanza_di? vs. is_a?


488

Qual è la differenza? Quando dovrei usare quale? Perché ce ne sono così tanti?


18
Sul perché entrambi is_a?ed kind_of?esistono: suppongo che faccia parte della filosofia progettuale di Ruby. Python direbbe che dovrebbe esserci solo un modo per fare qualcosa; Ruby ha spesso anche dei metodi, quindi puoi usare quello che suona meglio. È una questione di preferenza. Potrebbe essere in parte dovuto all'influenza giapponese: mi hanno detto che useranno una parola diversa per lo stesso numero a seconda della frase per renderla più piacevole. Matz potrebbe aver portato quell'idea nel suo linguaggio.
Nathan Long,

@NathanLong Non credo che i contatori giapponesi abbiano molto a che fare con questo; tutte le lingue hanno una sorta di accordo e non puoi andare a sostituire un contatore per un altro per la maggior parte del tempo (come, non puoi usare il contatore di cilindri per oggetti piatti; è semplicemente sbagliato). E ha più a che fare con la semantica che l'eufonia.
Casey,

Risposte:


622

kind_of?e is_a?sono sinonimi.

instance_of?è diverso dagli altri due in quanto restituisce solo truese l'oggetto è un'istanza di quella classe esatta, non una sottoclasse.

Esempio:

  • "hello".is_a? Objecte "hello".kind_of? Objectreturn trueperché "hello"è a Stringed Stringè una sottoclasse di Object.
  • Tuttavia "hello".instance_of? Objectritorna false.

77
A volte basta leggere meglio. Pensa @honda.kind_of? Care @person.is_a? Administrator, Ruby è tutto sull'estetica. In effetti, nota l'errore grammaticale ... con il supporto attivo puoi scrivere @person.is_an? Administrator:) ... Questo potrebbe essere diventato nel nucleo di Ruby ormai, in realtà.
rfunduk,

2
eh, questo è un motivo interessante. puoi spezzarlo, tu? come puoi scavalcare kind_of?ma no is_a??
Claudiu,

3
@thenduks, is_an?non è in ruby-1.9.2-p0. @Claudiu, no. is_a?è solo un alias dikind_of? . Entrambi i metodi invocare la stessa funzione c, rb_obj_is_kind_of.
ma11hew28,

9
@Matt: è possibile ignorare un alias senza sovrascrivere la funzione alias. Quindi sì, puoi eseguire l'override kind_of?senza eseguire l' override is_a?.
sepp2k,

4
Dov'è questo is_an?metodo ActiceSupport ?! Non è nella versione corrente delle rotaie e non riesco a trovare nulla su Google che sia deprecato.
Tom Lord,

22

Qual è la differenza?

Dalla documentazione:

- ( Booleano )instance_of?(class)
Restituisce trueif objè un'istanza di una determinata classe.

e:

- ( Booleano ) is_a?(class)
- ( Booleano )kind_of?(class)
Restituisce trueif classè la classe di obj, o if classè una delle superclassi di objo dei moduli inclusi in obj.

Se ciò non è chiaro, sarebbe bello sapere cosa non è esattamente chiaro, in modo che la documentazione possa essere migliorata.

Quando dovrei usare quale?

Mai. Usa invece il polimorfismo.

Perché ce ne sono così tanti?

Non chiamerei due "molti". Ce ne sono due, perché fanno due cose diverse.


3
Penso che la mia confusione sia che ce ne siano 3 e che 2 facciano la stessa cosa e abbiano nomi diversi. Sull'uso del polimorfismo - Sono d'accordo, ma la libreria standard ruby ​​è piena di usi di ciascuno di questi
Claudiu

4
Cosa intendi con polimorfismo? È lo stesso della digitazione dell'anatra?
Andrew Grimm,

2
Sì, sono uguali. La tipizzazione dell'anatra è una forma di polimorfismo.
SpaceGhost il

3
Spesso è meglio fare il polimorfismo, sì, ma ci sono casi limite in cui vuoi davvero sapere di avere una classe specifica, come quando hai a che fare con i file.
Automatico,

6

È più simile a Ruby chiedere agli oggetti se rispondono a un metodo che ti serve o meno, usando respond_to?. Ciò consente sia un'interfaccia minima che un'implementazione inconsapevole.

Ovviamente non è sempre applicabile, quindi c'è ancora la possibilità di chiedere una comprensione più conservativa del "tipo", che è una classe o una classe base, usando i metodi di cui stai chiedendo.


5
Dipende dalla situazione. Sia Comment che Blog possono rispondere a Created_at. In tale situazione is_a? è più appropriato IMHO
penkovsky

Non ha senso, se avessi bisogno di distinguere un oggetto Comment e uno Blog dall'altro, semplicemente non avresti usato Created_at per farlo. Ciò non preclude che potresti scrivere un metodo che accetta un oggetto che risponde a Created_at. Se non ha bisogno di nient'altro per fare il suo lavoro, allora puoi tranquillamente usarlo su Comment o Blog o praticamente su qualsiasi altro modello ActiveRecord.
Kingdon,

3

Inoltre non chiamerei due molti ( is_a?e kind_of?sono alias dello stesso metodo), ma se vuoi vedere più possibilità, rivolgi la tua attenzione al #classmetodo:

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

1
Grazie - in effetti stavo chiedendo in generale "quali informazioni sul tipo di run-time possono essere raccolte in Ruby e come" - e questo fornisce ampi esempi
Claudiu,
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.