Ruby: kind_of? Instanz_von? is_a?

487

Was ist der Unterschied? Wann soll ich welche verwenden? Warum gibt es so viele von ihnen?

Claudiu
quelle
18
Warum beides is_a?und kind_of?existiert: Ich nehme an, es ist Teil von Rubys Designphilosophie. Python würde sagen, dass es nur einen Weg geben sollte, etwas zu tun; Ruby hat oft auch Methoden, so dass Sie die verwenden können, die besser klingt. Es ist eine Frage der Präferenz. Dies kann teilweise auf den japanischen Einfluss zurückzuführen sein: Mir wurde gesagt, dass sie je nach Satz ein anderes Wort für dieselbe Nummer verwenden werden, damit es besser klingt. Matz hat diese Idee möglicherweise in sein Sprachdesign übernommen.
Nathan Long
@ NathanLong Ich glaube nicht, dass japanische Zähler viel damit zu tun haben. Alle Sprachen haben eine gewisse Übereinstimmung, und Sie können die meiste Zeit nicht einen Zähler durch einen anderen ersetzen (z. B. können Sie den Zylinderzähler nicht für flache Objekte verwenden; es ist einfach falsch). Und es hat mehr mit Semantik als mit Euphonie zu tun.
Casey

Antworten:

621

kind_of?und is_a?sind auch.

instance_of?unterscheidet sich von den beiden anderen darin, dass es nur zurückgibt, truewenn das Objekt eine Instanz dieser exakten Klasse und keine Unterklasse ist.

Beispiel:

  • "hello".is_a? Objectund "hello".kind_of? Objectkehre zurück, trueweil "hello"es ein Stringund Stringeine Unterklasse von ist Object.
  • "hello".instance_of? ObjectGibt jedoch zurück false.
sepp2k
quelle
77
Manchmal liest es sich einfach besser. Denken Sie @honda.kind_of? Carund @person.is_a? AdministratorRuby dreht sich alles um die Ästhetik. Beachten Sie in der Tat den Grammatikfehler ... mit aktiver Unterstützung können Sie schreiben @person.is_an? Administrator:) ... Das könnte es inzwischen tatsächlich in Ruby Core geschafft haben.
Rfunduk
2
Das ist ein interessanter Grund. Kannst du das brechen? wie kannst du kind_of?aber nicht überschreiben is_a??
Claudiu
3
@thenduks, is_an?ist nicht in Ruby-1.9.2-p0. @Claudiu, nein. is_a?ist nur ein Alias ​​vonkind_of? . Beide Methoden rufen dieselbe c-Funktion auf rb_obj_is_kind_of.
ma11hew28
9
@Matt: Sie können einen Alias ​​überschreiben, ohne die Alias-Funktion zu überschreiben. Also ja, Sie können überschreiben, kind_of?ohne zu überschreiben is_a?.
sepp2k
4
Wo ist diese ActiceSupport- is_an?Methode ?! Es ist nicht in der aktuellen Rails-Version und ich kann bei Google auch nichts darüber finden, dass es veraltet ist.
Tom Lord
22

Was ist der Unterschied?

Aus der Dokumentation:

- ( Boolescher Wert )instance_of?(class)
Gibt trueif zurück, wenn objes sich um eine Instanz der angegebenen Klasse handelt.

und:

- ( Boolean ) is_a?(class)
- ( Boolean )kind_of?(class)
Gibt zurück, trueob classes sich um die Klasse von objhandelt oder ob classes sich um eine der in enthaltenen Superklassen objoder Module handelt obj.

Wenn das unklar ist, wäre es schön zu wissen, was genau unklar ist, damit die Dokumentation verbessert werden kann.

Wann soll ich welche verwenden?

Noch nie. Verwenden Sie stattdessen Polymorphismus.

Warum gibt es so viele von ihnen?

Ich würde nicht zwei "viele" nennen. Es gibt zwei von ihnen, weil sie zwei verschiedene Dinge tun.

Jörg W Mittag
quelle
3
Ich glaube, meine Verwirrung war, dass es 3 gibt und dass 2 einfach dasselbe tun und unterschiedliche Namen haben. Über die Verwendung von Polymorphismus - ich stimme zu, aber die Ruby-Standardbibliothek ist voll von Verwendungen von jedem dieser
Claudiu
4
Was meinst du mit Polymorphismus? Ist es dasselbe wie beim Tippen von Enten?
Andrew Grimm
2
Ja, sie sind gleich. Das Tippen von Enten ist eine Form des Polymorphismus.
SpaceGhost
3
Es ist oft besser, Polymorphismus zu betreiben, ja, aber es gibt Grenzfälle, in denen Sie wirklich wissen möchten, dass Sie eine bestimmte Klasse haben, z. B. wenn Sie mit Dateien arbeiten.
Automatico
6

Es ist eher Ruby-ähnlich, Objekte zu fragen, ob sie auf eine von Ihnen benötigte Methode reagieren oder nicht respond_to?. Dies ermöglicht sowohl eine minimale Schnittstelle als auch eine Implementierung ohne Kenntnis der Programmierung.

Es ist natürlich nicht immer anwendbar, daher besteht immer noch die Möglichkeit, mit den von Ihnen gewünschten Methoden nach einem konservativeren Verständnis von "Typ" zu fragen, bei dem es sich um eine Klasse oder eine Basisklasse handelt.

kuonirat
quelle
5
Das hängt von der Situation ab. Sowohl Kommentar als auch Blog können auf created_at antworten. In einer solchen Situation ist_a? ist
meiner Meinung nach
Das macht keinen Sinn. Wenn Sie einen Kommentar und ein Blog-Objekt voneinander unterscheiden müssten, würden Sie create_at einfach nicht verwenden, um dies zu tun. Das schließt nicht aus, dass Sie eine Methode schreiben könnten, die ein Objekt verwendet, das auf created_at reagiert. Wenn es nichts anderes benötigt, um seine Arbeit zu erledigen, können Sie es sicher in Kommentaren oder Blogs oder in jedem anderen ActiveRecord-Modell verwenden.
Kingdon
3

Ich würde auch nicht zwei viele nennen ( is_a?und kind_of?Aliase derselben Methode sind), aber wenn Sie mehr Möglichkeiten sehen möchten, wenden Sie sich der #classMethode zu:

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
Boris Stitnicky
quelle
1
Vielen Dank - ich habe in der Tat allgemein gefragt, "welche Laufzeitinformationen in Ruby gesammelt werden können und wie" - und dies liefert zahlreiche Beispiele
Claudiu