Slide 1

Slide 1 text

Opaque Types in Scala Jens Grassel . . Wegtam GmbH

Slide 2

Slide 2 text

Was sind Opaque Types?

Slide 3

Slide 3 text

Also laut Doku... “Opaque types o er a sound abstraction over implementation details, without imposing performance overhead.” • Das klingt gut, aber Was heißt das? • Im Grunde: wie Type-Aliase, nur besser • statt: type Email = String • nehmen wir: opaque type Email = String

Slide 4

Slide 4 text

Unterschiede zu einfachen Type-Aliasen Type-Aliases geben nicht mehr Sicherheit: type Email = String def test(e: Email): String = ??? val str: String = "Just a string" test(str) // Wird compilieren... Opaque Types dagegen schon: opaque type Email = String def test(e: Email): String = ??? val str: String = "Just a string" test(str) // -> Type Mismatch Error!

Slide 5

Slide 5 text

Wie arbeiten wir mit diesen Typen?

Slide 6

Slide 6 text

Boilerplate... Boilerplate im Companion-Object: opaque type Email object Email { def apply(s: String): Email = s def from(s: String): Option[Email] = ??? } Erweiterung via Extension Methods: extension (e: Email) { def domain: DomainName = ??? }

Slide 7

Slide 7 text

Wie sicher ist das? val e = Email(null) // WIRD COMPILIEREN! val d = e.domain // -> AUTSCH! val e = Email.from(null) // besser (-> None) Achtung! Das bedeutet, daß es keine(!) ¨ Uberpr¨ ufung der Typerzeugung zur Compilierzeit gibt wie bei Refined Types!

Slide 8

Slide 8 text

Warum dann? • erspart uns Wrapper-Klassen • Typensicherheit abseits der Initialisierung trotzdem zur Compilierzeit • erm¨ oglicht spezifische from oder validate Methoden analog zu Refined • Operationen auf diesen Typen (Eq, Semigroup, Monoid) k¨ onnen definiert werden • weitere Operationen einfach via Extension Methods • Es gibt noch kein Refined (zumindest nicht vollst¨ andig) f¨ ur Scala . :-(

Slide 9

Slide 9 text

Unterschiede zu Refined Types

Slide 10

Slide 10 text

Vor- und Nachteile • keine ¨ Uberpr¨ ufung der Initialisierung zur Compilierzeit (das Killerfeature von Refined) • viel mehr Boilerplate • viel, viel mehr Boilerplate f¨ ur diverse Operationen, die mit Refined “frei Haus” kommen • Opaque Types sollten performanter sein, da Refined die Value Classes benutzt • keine “magische” Konvertierung mehr, die ggf. nur ¨ uber zus¨ atzliche Annotationen funktioniert

Slide 11

Slide 11 text

Besonderheiten Achtung! Die Definition von Funktionen ist notwendig, die zum Ursprungstyp zur¨ uck f¨ uhren! extension (e: Email): def toString: String = e extension (p: PortNumber): def toInt: Int = p

Slide 12

Slide 12 text

Vielen Dank!