Ich habe dieses Basismerkmal
%Vor% Wo TableQuery
ist scala.slick.lifted.TableQuery
Meine Unterklassen instanziieren TableQuery
like so:
Ich möchte die TableQuery
in der Basiseigenschaft instanziieren, möglicherweise unter Verwendung von lazy val
, d. h.
Ich habe mit Nachdenken gespielt, aber ich hatte nicht viel Glück.
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.
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:
Und Sie können es dann erweitern, ohne dass Sie TableQuery.apply
explizit aufrufen müssen:
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
.
Tags und Links scala reflection slick