Déterminer le type d'un objet en rubis

365

Je vais utiliser python comme exemple de ce que je recherche (vous pouvez le considérer comme un pseudocode si vous ne connaissez pas Python):

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

Je sais qu'en rubis je peux faire:

1.9.3p194 :002 > 1.class
 => Fixnum 

Mais est-ce la bonne façon de déterminer le type d'objet?

Zippy Zeppoli
la source
5
@ JörgWMittag Pourtant, l'AFAICR est ce que fait `type 'en Python, bien que ma mémoire soit floue. Vous auriez besoin isinstance ou vérifier les réponses. Mais en disant simplement "NON !!!" n'est pas vraiment utile, maintenant, n'est-ce pas? Pensez plutôt à être éducatif.
Dave Newton
4
@ JörgWMittag Bien que je sois sympathique, OP a fourni du code à imiter en Ruby. À moins que vous n'éduquiez réellement le PO en disant que le non n'est pas utile, l'OMI. Et même si vous le faisiez, ce ne serait probablement qu'à titre informatif, car OP définissait ce qu'il voulait à travers le code.
Dave Newton
5
@ JörgWMittag - dans Ruby, tout est un objet, il n'y a donc pas de types primitifs comme il en existe en Python (int, long, booléen, etc.). Par conséquent, dans Ruby, les classes sont des définitions de types. Cela ne se limite pas non plus à Ruby, le mot classe et type sont synonymes dans plusieurs autres langues, et plus largement dans la théorie de la POO.
ocodo
6
Puisque nous parlons vraiment de Ruby ici, les types et les classes sont synonymes, il n'y a pas de débat à ce sujet, toutes les valeurs sont des objets. Donc, pour quiconque parle simplement de Ruby, les classes sont des types. - ref: ruby-lang.org/en/about
ocodo
2
@ JörgWMittag Cet essai est assez informatif jusqu'à présent, et je lirai le reste lorsque j'en aurai l'occasion. En particulier, Cook semble expliquer très bien (et avec beaucoup plus de connaissances que moi) pourquoi il est incorrect de prétendre (comme l'a fait l'un de mes professeurs) que Python, Ruby et d'autres langages typés dynamiquement "ne sont pas vraiment des objets -oriented "(ce qu'il voulait probablement dire, sans s'en rendre compte, c'était qu'ils n'étaient pas orientés ADT). Mais Ruby n'est pas typé statiquement, donc il n'a pas d'ADT dans le sens que Cook décrit, donc vos objections sur la base de cette distinction ne sont pas utiles.
Kyle Strand

Réponses:

608

La bonne façon de déterminer le "type" d'un objet, qui est un terme bancal dans le monde Ruby, est d'appeler object.class.

Puisque les classes peuvent hériter d'autres classes, si vous voulez déterminer si un objet est "d'un type particulier", vous pouvez appeler object.is_a?(ClassName)pour voir s'il objectest de type ClassNameou dérivé de celui-ci.

Normalement, la vérification de type n'est pas effectuée dans Ruby, mais à la place, les objets sont évalués en fonction de leur capacité à répondre à des méthodes particulières, communément appelées " Duck typing ". En d'autres termes, s'il répond aux méthodes que vous souhaitez, il n'y a aucune raison d'être particulier sur le type.

Par exemple, object.is_a?(String)est trop rigide car une autre classe peut implémenter des méthodes qui la convertissent en chaîne, ou la faire se comporter de la même manière que String se comporte. object.respond_to?(:to_s)serait une meilleure façon de tester que l'objet en question fait ce que vous voulez.

tadman
la source
13
-1. #classne renvoie pas le type de l'objet, il renvoie sa classe . Le nom devrait être un cadeau mort. La classe et le type sont deux concepts complètement différents en OO.
Jörg W Mittag
78
@ Jörg W Mittag: Je ne suis pas d'accord. "Classe" et "vitesse du processeur" (pour prendre un exemple) sont deux concepts complètement différents, mais "classe" et "type" sont des concepts étroitement liés. Par exemple, voici ce que dit l'article de Wikipedia sur Class : "Dans la programmation orientée objet, une classe est une construction qui est utilisée pour définir un type distinct." tadman aidait le questionneur.
Teemu Leisti
18
@ JörgWMittag Dans Ruby, la chose la plus proche typeofde C, JavaScript et autres est class. Il n'y a pas de système de protocole formel dans Ruby comme dans d'autres langages, Objective-C étant le parent Smalltalk le plus proche de cela. Si vous définissez "type" comme "objet qui répond à un ensemble particulier de méthodes avec des résultats acceptables", il n'y a vraiment aucun moyen de l'affirmer. C'est tout simplement trop lâche. La plupart du temps en Ruby quand on fait référence au type d'un objet, il est entendu que vous parlez de la classe. J'ai utilisé le terme type entre guillemets pour cette raison.
tadman
14
@ Jörg W Mittag: Je continue d'affirmer que "classe" et "type" ne sont certainement pas des concepts complètement différents en OO, comme le démontre la citation. (Aussi: comment déclarer une variable en Java? En donnant soit le type ou la classe de la variable, suivi de son nom: " int i" ou " Integer j".) Tadman a répondu à la question d'une manière qui semblait satisfaire à la fois le questionneur et le grand public, tout en clarifiant la terminologie utilisée par Ruby. Je n'ai aucun intérêt à me lancer dans la coupe de cheveux académique sur les points les plus fins de la terminologie orientée objet, alors veuillez avoir le dernier mot.
Teemu Leisti
11
@TeemuLeisti La plupart des problèmes ici viennent du fait que tout dans Ruby est un objet, et a donc une classe, alors que dans pratiquement toutes les autres langues, il y a des types primitifs qui ne sont pas des objets et n'ont pas de classe, contrairement aux objets qui le font. Quand il n'y a pas de type pur, et aucun moyen d'en définir formellement un, le sens devient particulièrement flou dans le monde Ruby. Matz n'adhère pas strictement à une école de pensée particulière autre que la sienne.
tadman
81

vous pouvez également essayer: instance_of?

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

Souvent dans Ruby, vous ne vous souciez pas réellement de la classe de l'objet, en soi, vous vous souciez juste qu'il réponde à une certaine méthode. Ceci est connu sous le nom de Duck Typing et vous le verrez dans toutes sortes de bases de code Ruby.

Donc, dans de nombreux cas (sinon la plupart), il est préférable d'utiliser Duck Typing en utilisant #respond_to?(method):

object.respond_to?(:to_i)
Stuart M
la source
1
point valide. ne répond pas à la question mais atteint l'esprit de la question.
user566245
@ user566245 eh bien, il répond_à? (: la_question), mais comme vous l'avez dit, il ne répond pas à la question, donne simplement des informations connexes. Des réponses assez sûres doivent répondre à la question.
R. Rincón
17

Je dirais "oui". Comme "Matz" avait dit quelque chose comme ça dans une de ses conférences, "les objets Ruby n'ont pas de types." Pas tout, mais la partie qu'il essaie de nous transmettre. Pourquoi quelqu'un aurait-il alors dit "Tout est un objet"? Pour ajouter, il a dit: "Les données ont des types et non des objets".

Nous pourrions donc en profiter.

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

Mais Ruby ne se soucie pas beaucoup du type d'objet juste de la classe. Nous utilisons des classes et non des types. Toutes les données ont alors une classe.

12345.class

'my string'.class

Ils peuvent aussi avoir des ancêtres

Object.ancestors

Ils ont également des méta-classes mais je vais vous enregistrer les détails à ce sujet.

Une fois que vous connaissez la classe, vous pourrez rechercher les méthodes que vous pouvez utiliser pour cela. C'est là que le "type de données" est nécessaire. Si vous voulez vraiment entrer dans les détails, la recherche ...

"Le modèle d'objet Ruby"

C'est le terme utilisé pour la façon dont Ruby gère les objets. Tout est interne, vous ne voyez donc pas grand-chose, mais c'est agréable à savoir. Mais c'est un autre sujet.

Oui! La classe est le type de données. Les objets ont des classes et les données ont des types. Donc, si vous connaissez les bases de données, vous savez qu'il n'y a qu'un ensemble fini de types.

numéros de blocs de texte

Douglas G. Allen
la source
Par exemple,Object.ancestors # => [Object, Kernel, BasicObject]
Dorian