2017-11-14 5 views
1

Ich habe eine Klasse Word:Wie kann 'String # reverse' Nicht-String-Objekte zurückgeben?

class Word < String 
end 

w = Word.new("level") 
y = w.reverse 
y.class # => Word 

1) Wie ist das möglich? Word#reverse sollte einen String zurückgeben, da er String#reverse erbt, der eine String zurückgibt.

I hinzugefügt diesen Code:

class Word < String 
    attr_accessor :s 

    def magic 
    @s = Time.now 
    end 
end 

y.magic 
sleep(5) 
w.magic 
y.s == w # => false 
y == w # => true 

2) w und yWord sind und gleich sind, damit sie beide mit den gleichen Methoden, wie magic haben. Wo hat y die magic Methode erworben?

3) Wie lautet y == w ergibt true, während y.s und w.s ungleiche Werte zurückgeben?

+0

ich bin nicht sicher, was Ihre zweite Frage bedeutet. – sawa

Antwort

7

Während die Dokumentation für String#reverse Zustände:

Gibt eine neue Zeichenfolge mit den Zeichen von str in umgekehrter Reihenfolge.

und so könnten Sie einen Rückgabetyp String erwarten, wenn Sie die Methode Pop öffnen Sie die Zeile sehen

rev = rb_str_new_with_class(str, 0, RSTRING_LEN(str)); 

und dass rev ist, was tatsächlich zurückgegeben wird. Mein C ist ziemlich rostig, aber wenn man sich den C-Code für Ruby ansieht, scheint diese Methode rb_str_new_with_class genau das zu tun, was sie sagt, sie erzeugt eine neue Instanz der Klasse str, in diesem Fall Word. Was also die Dokumentation bedeutet, wenn sie sagt, dass sie eine neue Zeichenkette zurückgibt, ist, dass sie eine neue Instanz der Klasse zurückgibt, die diese Zeichenkette ist, in den meisten Fällen String. So

zu wissen, dass es eine neue Instanz der Klasse, was schafft der aktuelle String ist, ist es einfach, zu sehen, wie w.reverse ein magic Verfahren mit endete ... weil Word ihm die Methode gab, und es ist ein Word.

Und schließlich, wie sind sie gleich? Sie definieren keine neue == Methode auf Word, so dass es die übergeordnete String#== Methode, die nicht weiß, oder kümmern, dass es Instanzvariablen gibt und vergleicht nur die Werte der Zeichenfolge, zwingt Dinge mit to_str wenn nötig und in der Lage, Sie könnte sogar tun:

Word.new("level") == "level" # => true 

(Hinweis: ich bin nicht wirklich sicher, ob Word gezwungen wird oder nicht.)