2013-02-17 11 views
6

Ich habe den Well Grounded Rubyist gelesen und erwähnt, wie eine Klasse die Instanzmethoden ihrer Superklasse erbt, so dass Objekte der Klasse diese Instanzmethoden aufrufen können. Hier ein Beispiel:Verstehen der Ruby-Vererbung

class C 
    def run_instance_method 
    puts "This is an instance method." 
    end 
    def C.run_class_method 
    puts "This is a class method." 
    end 
end 

class D < C 
end 

Nach dem, was ich gelesen habe, ist es immer, dass die Klasse D beschrieben worden wäre nur die Instanzmethoden der Klasse C erben (in diesem Fall das C :: run_class_method nicht vererbt werden würde durch D). Doch nach dem obigen Code ausgeführt wird, merke ich, dass:

D.run_class_method # => "This is a class method." 

Hier ist meine Vermutung, warum dies geschieht, und lassen Sie es mich wissen, ob dies das richtige Verständnis ist. Wenn es eine Instanz d der Klasse D gibt und Sie versuchen, d.run_instance_method auszuführen, durchsucht dieses Objekt seinen Methoden-Suchpfad und prüft, ob diese Methode in ihrer Singleton-Klasse, ihrer eigenen Klasse oder in ihren Oberklassen definiert ist. Da run_instance_method in Klasse C definiert ist, treten keine Probleme auf und run_instance_method wird aufgerufen. Für das Klassenobjekt D (welches eine Unterklasse von C und Object ist) wird, wenn D.run_class_method aufgerufen wird, erneut der Methoden-Suchpfad für das D-Klassenobjekt überprüft. Wieder wird Ruby es im Klassenobjekt C finden.

Ist diese Argumentation korrekt?

Antwort

5

Klassenmethoden können genauso wie Instanzmethoden geerbt und außer Kraft gesetzt werden. Wenn Ihre Elternklasse eine Klassenmethode definiert, erbt die Unterklasse diese Methode. Das heißt, wenn Ihre Unterklasse ihre eigene Klassenmethode nicht definiert, dann erbt sie von ihrer Oberklasse.

Als Empfehlung: Wenn Sie eine Klassenmethode mit einem expliziten Empfänger aufrufen, sollten Sie sich nicht auf Vererbung verlassen. Rufen Sie die Klassenmethode immer über die Klasse auf, die sie definiert. Andernfalls wäre es für jemanden, der auf Ihren Code angewiesen ist, sehr schwierig, die Elternklasse zu finden, die die Klassenmethode definiert.

Zurück zu Ihrer ursprünglichen Annahme: der Aufruf einer Klassenmethode aus einer Unterklasse ist möglich, weil die Klassenmethoden Instanzmethoden der eigenclass sind.

Im Allgemeinen ist es klarer, Klassenmethoden als einzelne Singleton-Methoden zu definieren, ohne die Eigenklasse explizit zu öffnen.

Für eine klare Erklärung lesen The Ruby Programming Language von David Flanagan und Yukihiro Matsumoto

+0

Dank für die Erklärung. Können Sie mich korrigieren, wenn ich mit dieser Erklärung nicht einverstanden bin: Grundsätzlich sind alle Klassenmethoden in ihrer Eigenklasse als Instanzmethoden enthalten. Wenn die Klasse D von ihrer Oberklassenklasse C erbt, erbt die Eigenklasse Klasse D implizit auch die Eigenklasse der Klasse C. Aus diesem Grund kann das Klassenobjekt D .run_class_method aufrufen. Ist das genau? – wmock

+1

Genau! Wenn Ruby einen Methodenaufruf-Ausdruck evaluiert, muss zuerst herausgefunden werden, welche Methode aufgerufen werden muss. Dies nennt man 'Method Lookup': Suchen Sie zunächst nach der Methodendefinition in der Selbstklasse, wenn keine Methode gefunden wird, suchen Sie dann in der Klasseneltern bis zum Kettenstamm. –

2

Nicht sehr genau. Hier ist ein anderes Konzept versteckt, das metaclass oder eigenclass genannt wird. Die Klassenmethode wird von der Eigenklasse geerbt. Weitere Informationen dazu finden Sie unter Ruby Hacking Guide. (Suchen Sie auf der Seite nach "Klassenmethoden", wenn Sie nicht alle lesen möchten.)