Ruby Methode zu einer Klasse hinzufügen

7

Angenommen, ich habe eine Klasse:

%Vor%

Um dieser Klasse eine Methode hinzuzufügen, kenne ich 2 Optionen:

  1. Erneutes Öffnen der Klasse und Implementieren der Methode:

    %Vor%
  2. mit class_eval zur Implementierung der Methode:

    %Vor%

Was ist der Unterschied? Welcher ist besser?

    
Saman Mohamadi 30.12.2015, 11:29
quelle

2 Antworten

15

Tatsächlich gibt es ein paar andere Möglichkeiten, einer Klasse neue Methoden hinzuzufügen. Sie können beispielsweise auch die Methoden in einem Modul definieren und das Modul in die ursprüngliche Klasse einfügen.

%Vor%

Es gibt kein wirklich besseres oder schlechteres. Die zwei (oder drei) Wege, die Sie erwähnten, haben ein unterschiedliches Verhalten und Sie möchten vielleicht das eine oder andere verwenden, je nach Ihrem Bedürfnis (oder Ihrer Präferenz). In den meisten Fällen ist dies subjektiv. In anderen Fällen hängt es wirklich davon ab, wie Ihr Code strukturiert ist.

Der Hauptunterschied zwischen dem erneuten Öffnen der Klasse und der Verwendung von class_eval besteht darin, dass die erste Klasse ebenfalls eine Klassendefinition ist, während die zweite die ursprüngliche Klasse bereits definiert.

In der Praxis kann das erneute Öffnen der Klasse in einigen Fällen zu unerwarteten Nebenwirkungen führen. Nehmen wir an, Sie haben Foo in der Datei lib/foo.rb mit einer Reihe von Methoden definiert. Dann öffnest du wieder Foo in config/initializers/extra.rb und fügst die bar Methode hinzu.

In myclass.rb verwenden Sie Foo , aber anstatt lib/foo.rb manuell zu verwenden, verlassen Sie sich auf eine automatische Ladefunktion.

Wenn extra.rb vor lib/foo.rb geladen wird, könnte die Foo -Klasse in Ihrer Umgebung bereits definiert sein, und Ihr Code lädt lib/foo.rb nicht. Was Sie haben werden, ist eine Klasse Foo , die nur die von Ihnen definierte Erweiterung bar und nicht die ursprüngliche Foo eins enthält.

Mit anderen Worten, wenn Sie aus irgendeinem Grund die Klasse erneut öffnen, um einige Methoden hinzuzufügen, ohne sicherzustellen, dass die vollständige Originalklassendefinition zuerst (oder danach) geladen wird, kann Ihr Code brechen, wenn er auf autoload basiert.

Umgekehrt ruft Foo.class_eval eine Methode für Foo auf, daher erwartet es, dass die ursprüngliche Foo -Definition bereits zu dem Zeitpunkt vorhanden ist, an dem Sie versuchen, neue Methoden hinzuzufügen. Dadurch wird sichergestellt, dass beim Hinzufügen neuer Methoden die Klasse Foo bereits definiert ist.

Zusammenfassend besteht der Hauptunterschied darin, dass das Wiedereröffnen der Klasse es Ihnen erlaubt (im Guten oder im Schlechten), Methoden zu einer Klasse hinzuzufügen, die noch nicht geladen wurde, während class_eval erfordert, dass die Klasse bereits definiert ist.

Im Allgemeinen bevorzuge ich den zweiten Ansatz, es sei denn, ich definiere Namespace-Unterklassen oder wiederöffnende Klassen, in denen ich die volle Kontrolle habe, da der Code in großen Codebasen mehr wartbar bleibt. Tatsächlich verwende ich normalerweise Mixins, wenn ich Klassen von Drittanbietern erweitere, so dass ich die gesamte Vorfahrenkette der Methode behalten kann, wenn ich bestehende Methoden überschreiben muss.

    
Simone Carletti 30.12.2015, 11:45
quelle
5

Der zweite Ansatz ist sehr praktisch, wenn Sie etwas Dynamisches brauchen. Ruby hat tatsächlich mehrere Bereiche:

%Vor%

Mit class_eval können Sie Bereiche teilen.

%Vor%     
Зелёный 30.12.2015 11:54
quelle

Tags und Links