Elegante Gruppierung von impliziten Wertklassen

9

Ich schreibe eine Reihe von impliziten Scala -Wrapperklassen für eine vorhandene Java -Bibliothek (damit ich diese Bibliothek dekorieren kann ) es ist für Scala Entwickler bequemer.

Als ein einfaches Beispiel nehmen wir an, dass die Bibliothek Java (die ich nicht ändern kann) eine Klasse wie die folgende hat:

%Vor%

Nun möchte ich sagen, dass ich diese Klasse mit Scala -artigen Gettern und Settern dekorieren möchte. Ich kann dies mit der folgenden impliziten Klasse tun:

%Vor%

Das Schlüsselwort implicit teilt dem Scala -Compiler mit, dass Instanzen von Value implizit in Instanzen von RichValue konvertiert werden können (sofern letzterer im Geltungsbereich ist). Jetzt kann ich Methoden, die in RichValue definiert sind, auf Instanzen von Value anwenden. Beispielsweise:

%Vor%

(Einverstanden, das ist kein sehr netter Code und ist nicht genau funktional . Ich versuche nur, einen einfachen Anwendungsfall zu demonstrieren.)

Leider erlaubt Scala implicit -Klassen nicht als oberste Ebene, also müssen sie innerhalb eines package object , object , class oder trait definiert werden und nicht nur in package . (Ich habe keine Ahnung, warum diese Einschränkung notwendig ist, aber ich gehe davon aus, dass es für die Kompatibilität mit impliziten Konvertierungsfunktionen steht.)

Allerdings erweitere ich auch RichValue von AnyVal , um dies zu einer -Wertklasse zu machen. Wenn Sie mit ihnen nicht vertraut sind, ermöglichen sie dem Scala -Compiler, Zuordnungsoptimierungen vorzunehmen. Insbesondere muss der Compiler nicht immer Instanzen von RichValue erstellen und kann direkt auf das Konstruktorargument der -Wertklasse zugreifen.

Mit anderen Worten, die Verwendung einer Scala-Klasse mit implizitem Wert als Wrapper hat einen sehr geringen Leistungsaufwand, was gut ist. : -)

Eine wesentliche Einschränkung der -Wertklassen besteht jedoch darin, dass sie nicht innerhalb einer class oder einer trait definiert werden können; Sie können nur Mitglieder von package s, package object s oder object s sein. (Dies ist so, dass sie keinen Zeiger auf die äußere Klasseninstanz aufrechterhalten müssen.)

Eine implizite Wertklasse muss beide Abhängigkeiten berücksichtigen und kann daher nur innerhalb von package object oder object definiert werden.

Und darin liegt das Problem. Die Bibliothek, die ich umschließe, enthält eine tiefe Hierarchie von Paketen mit einer großen Anzahl von Klassen und Schnittstellen. Idealerweise möchte ich meine Wrapper-Klassen mit einer einzigen import -Anweisung importieren können, z.

%Vor%

, um sie so einfach wie möglich zu machen.

Die einzige Möglichkeit, dies zu erreichen, besteht derzeit darin, alle meine impliziten Wertklassen -Definitionen in eine einzige package object (oder object ) innerhalb einer einzigen Quelldatei zu setzen:

%Vor%

Das ist jedoch alles andere als ideal, und ich würde es vorziehen, die Paketstruktur der Zielbibliothek zu spiegeln und trotzdem alles über eine einzige import -Anweisung in den Geltungsbereich zu bringen.

Gibt es einen einfachen Weg, dies zu erreichen, ohne die Vorteile dieses Ansatzes zu opfern?

(Ich weiß zum Beispiel, dass ich, wenn ich darauf verzichte, diese Wrappers -Wertklassen zu machen, sie in einer Reihe verschiedener trait s - eins für jedes Komponentenpaket - definieren kann und meine root package object erweitert alle von ihnen, bringt alles durch einen einzigen Import in den Geltungsbereich, aber ich möchte die Leistung nicht zugunsten der Bequemlichkeit opfern.)

    
Mike Allen 12.02.2018, 23:33
quelle

1 Antwort

3
%Vor%

Ist im Wesentlichen eine Syntaxzucker für die folgenden zwei Definitionen

%Vor%

(was Sie vielleicht sehen, ist, warum implizite Klassen innerhalb von Merkmalen, Objekten oder Klassen stehen müssen: sie haben auch den passenden def )

Es gibt nichts, was diese beiden Definitionen erfordert, um zusammen zu leben. Sie können sie in separate Objekte einfügen:

%Vor%

Oder in Eigenschaften:

%Vor%     
Oleg Pyzhcov 13.02.2018, 06:31
quelle