Ruby definiert #clone
in Objekt .
Zu meiner Überraschung, heben einige Klassen Exceptions auf, wenn sie es nennen.
Ich fand NilClass , TrueClass , FalseClass , Fixnum dieses Verhalten.
1) Gibt es eine komplette Liste von Klassen (zumindest Core-Klassen), die #clone
nicht zulassen?
Oder gibt es eine Möglichkeit zu erkennen, ob eine bestimmte Klasse #clone
unterstützt?
2) Was ist falsch mit 42.clone
?
Ich glaube nicht, dass es eine formelle Liste gibt, zumindest solange Sie nicht die Quelle lesen. Der Grund 2) funktioniert nicht, weil eine Optimierung auf Fixnums angewendet wurde. Sie werden intern als ihre tatsächlichen Werte gespeichert / übergeben (also sind wahr, falsch und null) und nicht als Zeiger. Die naive Lösung besteht darin, dass 42.clone
die gleiche 42
zurückgibt, aber dann würde die invariante obj.clone.object_id != obj.object_id
nicht länger halten, 42.clone
würde nicht tatsächlich geklont.
Fixnum ist eine spezielle Klasse, die von der Sprache speziell behandelt wird. Ab dem Zeitpunkt, an dem das Programm gestartet wird, gibt es genau eine Fixnum für jede Zahl, die die Klasse darstellen kann, und sie erhalten eine spezielle Darstellung, die keinen zusätzlichen Platz benötigt - auf diese Weise werden grundlegende mathematische Operationen nicht zugeordnet und nicht zugewiesen Erinnerung wie verrückt. Aus diesem Grund kann es nicht mehr als eine 42 geben.
Für die anderen haben sie alle eines gemeinsam: Sie sind Singletons. Es gibt nur eine Instanz einer Singleton-Klasse per Definition, daher ist es ein Fehler, sie zu klonen.Ich weiß immer noch nicht, wie man richtig auf Klonbarkeit testet, aber hier ist eine sehr klobige, bösartige Methode, um die Klonbarkeit mit Fehlerfallen zu testen:
%Vor%Und hier können Sie sogar das Unklare klonen. Zumindest für die wenigen Klassen, mit denen ich es vermasselt habe.
%Vor%Hier einige Beispieltests:
%Vor% Ich habe einen git grep "can't clone"
von YARVs Quellcode gemacht und habe
Die erste und dritte Zeile zeigen an, dass Sie kein Singleton klonen können.
Die zweite Zeile bezieht sich auf rb_special_const_p(obj)
. Aber das geht über meinen Horizont hinaus.
Sie können unveränderliche Klassen nicht klonen. I.e. Sie können nur eine Instanz von Objekt 42 (als Fixnum) haben, aber viele Instanzen von "42" (weil String veränderbar ist). Sie können auch keine Symbole klonen, da sie etwas wie unveränderliche Zeichenfolgen sind.
Sie können das in IRB mit object_id-Methode überprüfen. (Symbole und Fixnums geben Ihnen dieselbe Objekt-ID nach wiederholten Aufrufen)
Rails scheint die von Ihnen erwähnten Klassen um eine "duplicable? ()" - Methode zu erweitern.