Scala reflection zum instanziieren von scala.slick.lifed.TableQuery

8

Ich habe dieses Basismerkmal

%Vor%

Wo TableQuery ist scala.slick.lifted.TableQuery

Meine Unterklassen instanziieren TableQuery like so:

%Vor%

Ich möchte die TableQuery in der Basiseigenschaft instanziieren, möglicherweise unter Verwendung von lazy val , d. h.

%Vor%

Ich habe mit Nachdenken gespielt, aber ich hatte nicht viel Glück.

    
ic3b3rg 12.05.2015, 06:05
quelle

1 Antwort

8

Wenn ich richtig verstehe, was Sie wollen, ist in der Lage zu erweitern MyBase , indem Sie einfach M und T definieren, ohne die TableQuery in jeder abgeleiteten Klasse explizit instanziieren zu müssen.

Die Verwendung von Reflektion ist nicht wirklich eine Option, da normalerweise TableQuery.apply verwendet wird. dafür (wie in val query = TableQuery[MyTable] ), und dies wird durch ein Makro implementiert, Sie haben also ein "Runtime vs Compile-Time" Problem.

Wenn Sie MyBase unbedingt als Merkmal benötigen (im Gegensatz zu einer Klasse), sehe ich keine brauchbare Lösung. Wenn Sie jedoch MyBase in eine Klasse und verwandeln können und M und T in Typparameter (anstelle von abstrakten Typen) umwandeln, gibt es mindestens eine Lösung. Wie ich in einer anderen verwandten Frage angedeutet habe ( Wie generische Art zu definieren Scala? ), du kannst Definieren Sie eine Typklasse (zB TableQueryBuilder ), um den Aufruf von TableQuery.apply (an dem Punkt, an dem der konkrete Typ bekannt ist) zusammen mit einem impliziten Makro (zB TableQueryBuilder.builderForTable ) zu erfassen eine Instanz dieser Typklasse. Sie können dann eine Methode definieren (sagen wir TableQueryBuilder.build ), um die TableQuery tatsächlich zu instanziieren, die nur an den Job an die Typklasse delegiert wird.

%Vor%

Der Nettoeffekt ist, dass Sie den konkreten Wert des Typs T nicht mehr benötigen, um TableQuery[T] instanziieren zu können. vorausgesetzt, Sie haben eine implizite Instanz von TableQueryBuilder[T] im Bereich. Mit anderen Worten, Sie können die Notwendigkeit verschieben, den konkreten Wert von T zu kennen. bis zu dem Punkt, wo Sie es tatsächlich wissen.

MyBase (jetzt eine Klasse) kann dann wie folgt implementiert werden:

%Vor%

Und Sie können es dann erweitern, ohne dass Sie TableQuery.apply explizit aufrufen müssen:

%Vor%

Was hier passiert, ist, dass im Konstruktor von Derived ein impliziter Wert für TableQueryBuilder[Coffees] implizit ist übergeben an den Konstruktor von MyBase .

Der Grund, warum Sie dieses Muster nicht anwenden können, wenn MyBase ein Merkmal ist, ist ziemlich banal: Merkmalskonstruktoren können keine Parameter haben, geschweige denn implizite Parameter, so dass es keinen impliziten Weg geben würde Übergeben der Instanz TableQueryBuilder .

    
Régis Jean-Gilles 20.05.2015, 15:57
quelle

Tags und Links