2017-05-29 1 views
4

Ich habe eine Testsuite, die Slick für DB-Zugriff verwendet. Einige Tests in dieser Suite greifen auf die DB zu, andere nicht. Meine Suite hatKann der implizite Wert auch ein Lazy-Wert sein, wenn er als impliziter Methodenparameterwert verwendet wird?

implicit val db = DB.getDB

die effektiv DataBaseDef am Anfang der Suite Ausführung initialisiert. Dieser Wert wird dann als impliziter Parameterwert für einige Methoden verwendet. Auch sie hat die afterAll() die die db am Ende der Suite Ausführung schließt:

override def afterAll():Unit={ 
    db.close() 
    super.afterAll() 
    } 

Wenn ich nun geändert: implicit lazy val db = DB.getDB dann, was genau passieren wird?

Wenn ich nur einen Test ausführen, der nicht die DB verwendet dann wird die Verbindung nicht initialisiert und in der afterAll() wird es immer noch versuchen, die Verbindung zu schließen, und ich habe ein Problem in diesem Fall, oder? Ich versuchte zu laufen, aber kein Fehler ist passiert und keine Ausnahme wurde geworfen ...

Mein Wissen über implicits ist nicht genug, um mir zu helfen, es in Kombination mit faul zu verstehen.

Antwort

7

dann was genau wird passieren?

Der Wert wird erst beim ersten Zugriff initialisiert.

es wird immer noch versuchen, die Verbindung zu schließen, und ich habe ein Problem in diesem Fall, richtig?

Wenn Sie db.close() zugreifen, wird es zunächst um den Wert initialisieren, was bedeutet, dass es DB.getDb vor dem Schließen der Verbindung nennen. Das bedeutet, obwohl Sie dies nicht beabsichtigt haben, wird die Verbindung immer noch initialisiert und dann sofort geschlossen, weshalb Sie keine Ausnahme sehen.

+0

Sie haben Recht. Ich dachte mehr nach dem Posten der Frage und das wurde mir klar. Noch möchte ich den Effekt von "Lazy" Modifikator auf impliziten Parameter Wert Entdeckung in Methoden Aufruf verdeutlichen. Könntest du damit helfen? –

+0

oder ich kann sicher die Standardregel annehmen: wenn nichts darüber in den Spezifikationen als faul gesagt wird, hat keine Wirkung in dieser Hinsicht? –

+0

@AlexanderArendar Wenn Sie ein implizites Lazy-Val haben, das von einer aufgerufenen Methode benötigt wird, wird der Wert materialisiert. In diesem Fall wird die DB Verbindung hergestellt. –

1

Um die akzeptierte Antwort hinzuzufügen, möchte ich darauf hinweisen, dass implizit zur Kompilierzeit aufgelöst werden, während vallazy val und def Auswirkungen nur zur Laufzeit haben.

Wenn Sie einen Bezeichner als implizit definieren, teilt er dem Compiler mit, dass Sie Zugriff auf einen impliziten Wert des angegebenen Typs haben, sodass jede Methode, die einen solchen impliziten Parameter benötigt, diesen verwenden wird; Umgekehrt wird jeder Aufruf einer Methode, die einen Wert dieses Typs benötigt, einen Compilerfehler auslösen, wenn Sie keinen impliziten Bezeichner eines bestimmten Typs deklarieren. Sobald der Code jedoch kompiliert ist, sind keine Implikationen mehr erforderlich (sie wurden durch explizite Verweise auf die relevante Kennung ersetzt, abhängig vom Umfang).

nun bei Laufzeit, wenn eine implizite Kennung aufgerufen wird, wird es mit den Standardregeln instanziert werden, so dass es entweder instanziiert und memoized bei Definition werden kann, wenn es sich um eine val ist, instanziiert und bei Nutzung memoized wenn es ein lazy val oder instanziiert bei jeder Verwendung, wenn es eine def ist. Die Tatsache, dass es sich um einen impliziten Parameter handelte, hat keinen Einfluss auf die Instanziierungsregeln.

+0

Danke Cyrille für eine nützliche und detaillierte Erläuterung. –

Verwandte Themen