Bestimmen des Typs eines Objekts in Ruby

365

Ich werde Python als Beispiel für das verwenden, wonach ich suche (Sie können es sich als Pseudocode vorstellen, wenn Sie Python nicht kennen):

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

Ich weiß in Rubin, was ich tun kann:

1.9.3p194 :002 > 1.class
 => Fixnum 

Aber ist dies der richtige Weg, um den Typ des Objekts zu bestimmen?

Zippy Zeppoli
quelle
5
@ JörgWMittag AFAICR ist genau das, was `type` in Python macht, obwohl mein Gedächtnis verschwommen ist. Sie benötigen isinstance oder suchen nach Antworten. Aber einfach "NEIN !!!" sagen ist jetzt nicht wirklich hilfreich, oder? Betrachten Sie stattdessen als lehrreich.
Dave Newton
4
@ JörgWMittag Während ich mitfühlend bin, hat OP Code zur Nachahmung in Ruby bereitgestellt. Es sei denn , Sie tatsächlich erziehen die OP sagen Neins ist nicht hilfreich, IMO. Und selbst wenn Sie dies tun würden, wäre dies wahrscheinlich nur zu Informationszwecken, da OP definiert hat, was er / sie durch Code haben möchte.
Dave Newton
5
@ JörgWMittag - in Ruby ist alles ein Objekt, daher gibt es keine primitiven Typen wie in Python (int, long, boolean usw.). Daher sind Klassen in Ruby Typdefinitionen. Dies ist auch nicht auf Ruby beschränkt, die Wortklasse und der Typ sind synonym in mehreren anderen Sprachen und allgemeiner in der OOP-Theorie.
ocodo
6
Da wir hier wirklich über Ruby sprechen, sind Typen und Klassen synonym, es gibt keine Debatte darüber, alle Werte sind Objekte. Also für jedermann einfach reden über Ruby Klassen sind Typen. - Ref: ruby-lang.org/en/about
ocodo
2
@ JörgWMittag Dieser Aufsatz ist bisher recht informativ und ich werde den Rest lesen, wenn ich die Gelegenheit dazu bekomme. Insbesondere scheint Cook recht gut zu artikulieren (und mit viel mehr Hintergrundwissen als ich), warum es falsch ist zu behaupten (wie einer meiner Professoren), dass Python, Ruby und andere dynamisch typisierte Sprachen "nicht wirklich objektiv sind -orientiert "(was er wahrscheinlich meinte, ohne es zu merken, war, dass sie nicht ADT-orientiert waren). Ruby ist jedoch nicht statisch typisiert, sodass es keine ADTs in dem Sinne gibt, wie Cook es beschreibt. Daher sind Ihre Einwände aufgrund dieser Unterscheidung nicht hilfreich.
Kyle Strand

Antworten:

608

Der richtige Weg, um den "Typ" eines Objekts zu bestimmen, was in der Ruby-Welt ein wackeliger Begriff ist, ist das Aufrufen object.class.

Da Klassen von anderen Klassen erben können, können Sie aufrufen object.is_a?(ClassName), ob ein Objekt "von einem bestimmten Typ" ist, um festzustellen , ob objectes vom Typ ist ClassNameoder von diesem abgeleitet ist.

Normalerweise wird die Typprüfung nicht in Ruby durchgeführt, sondern Objekte werden anhand ihrer Fähigkeit bewertet, auf bestimmte Methoden zu reagieren, die üblicherweise als " Ententypisierung " bezeichnet werden. Mit anderen Worten, wenn es auf die gewünschten Methoden reagiert, gibt es keinen Grund, den Typ genau zu bestimmen.

Ist beispielsweise object.is_a?(String)zu starr, da eine andere Klasse möglicherweise Methoden implementiert, die sie in eine Zeichenfolge konvertieren, oder dafür sorgt, dass sie sich identisch mit dem Verhalten von Zeichenfolgen verhält. object.respond_to?(:to_s)Dies wäre ein besserer Weg, um zu testen, ob das betreffende Objekt das tut, was Sie wollen.

Tadman
quelle
13
-1. #classgibt nicht den Typ des Objekts zurück, sondern seine Klasse . Der Name sollte ein totes Werbegeschenk sein. Klasse und Typ sind zwei völlig unterschiedliche Konzepte in OO.
Jörg W Mittag
78
@ Jörg W Mittag: Ich bin anderer Meinung. "Klasse" und "Prozessorgeschwindigkeit" (um ein Beispiel auszuwählen) sind zwei völlig unterschiedliche Konzepte, aber "Klasse" und "Typ" sind eng verwandte Konzepte. In dem Wikipedia-Artikel zu Class heißt es beispielsweise: "In der objektorientierten Programmierung ist eine Klasse ein Konstrukt, mit dem ein bestimmter Typ definiert wird." Tadman war dem Fragesteller hilfreich.
Teemu Leisti
18
@ JörgWMittag In Ruby ist typeofC, JavaScript und andere am nächsten dran class. In Ruby gibt es kein formales Protokollsystem wie in anderen Sprachen, wobei Objective-C der engste Smalltalk-Verwandte ist. Wenn Sie "Typ" als "Objekt definieren, das auf einen bestimmten Satz von Methoden mit akzeptablen Ergebnissen reagiert", gibt es wirklich keine Möglichkeit, dies zu behaupten. Es ist einfach zu locker. Wenn Sie sich in Ruby meistens auf den Typ eines Objekts beziehen, wird davon ausgegangen, dass Sie über die Klasse sprechen. Genau aus diesem Grund habe ich den Begriff Typ in Anführungszeichen verwendet.
Tadman
14
@ Jörg W Mittag: Ich behaupte weiterhin, dass "Klasse" und "Typ" in OO sicherlich keine völlig unterschiedlichen Konzepte sind, wie das Zitat zeigt. (Außerdem: Wie deklariert man eine Variable in Java? Geben Sie entweder den Typ oder die Klasse der Variablen an, gefolgt von ihrem Namen: " int i" oder " Integer j".) Tadman beantwortete die Frage auf eine Weise, die beide Fragesteller zufrieden zu stellen schien und das allgemeine Publikum, während die von Ruby verwendete Terminologie geklärt wird. Ich habe kein Interesse daran, mich über die Feinheiten der objektorientierten Terminologie hinweg akademisch zu spalten. Bitte haben Sie das letzte Wort.
Teemu Leisti
11
@TeemuLeisti Das meiste Problem besteht darin, dass alles in Ruby ein Objekt ist und somit eine Klasse hat, während es in praktisch jeder anderen Sprache primitive Typen gibt, die keine Objekte sind und keine Klasse haben, im Gegensatz zu Objekten, die dies tun. Wenn es keinen reinen Typ gibt und keine Möglichkeit, einen formal zu definieren, wird die Bedeutung in der Ruby-Welt besonders verschwommen. Matz hält sich hier nicht strikt an eine andere Denkrichtung als seine eigene.
Tadman
81

Sie könnten auch versuchen: instance_of?

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

In Ruby ist es Ihnen oft egal, was die Klasse des Objekts an sich ist, es ist Ihnen nur wichtig, dass es auf eine bestimmte Methode reagiert. Dies ist als Duck Typing bekannt und wird in allen möglichen Ruby-Codebasen angezeigt.

In vielen (wenn nicht den meisten) Fällen ist es am besten, Duck Typing zu verwenden, indem Sie #respond_to?(method):

object.respond_to?(:to_i)
Stuart M.
quelle
1
gutes Argument. beantwortet die Frage nicht, trifft aber den Geist der Frage.
user566245
@ user566245 Nun, es reagiert auf? (: the_question), aber wie Sie sagten, es beantwortet die Frage nicht, sondern gibt nur verwandte Informationen. Ziemlich sichere Antworten müssen die Frage beantworten.
R. Rincón vor
17

Ich würde Ja sagen". Wie "Matz" in einem seiner Vorträge so etwas gesagt hatte: "Ruby-Objekte haben keine Typen." Nicht alles, aber der Teil, den er versucht, uns zu vermitteln. Warum hätte dann jemand "Alles ist ein Objekt" gesagt? Um hinzuzufügen, sagte er "Daten haben Typen, keine Objekte".

Das könnte uns also gefallen.

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

Aber Ruby interessiert sich nicht so sehr für den Objekttyp, nur für die Klasse. Wir verwenden Klassen, keine Typen. Alle Daten haben dann eine Klasse.

12345.class

'my string'.class

Sie können auch Vorfahren haben

Object.ancestors

Sie haben auch Meta-Klassen, aber ich werde Ihnen die Details dazu speichern.

Sobald Sie die Klasse kennen, können Sie nachschlagen, welche Methoden Sie dafür verwenden können. Dort wird der "Datentyp" benötigt. Wenn Sie wirklich ins Detail gehen möchten, schauen Sie nach ...

"Das Ruby-Objektmodell"

Dies ist der Begriff für den Umgang von Ruby mit Objekten. Es ist alles intern, so dass Sie nicht wirklich viel davon sehen, aber es ist schön zu wissen. Aber das ist ein anderes Thema.

Ja! Die Klasse ist der Datentyp. Objekte haben Klassen und Daten haben Typen. Wenn Sie sich mit Datenbanken auskennen, wissen Sie, dass es nur eine begrenzte Anzahl von Typen gibt.

Text blockiert Zahlen

Douglas G. Allen
quelle
Zum BeispielObject.ancestors # => [Object, Kernel, BasicObject]
Dorian