2011-09-16 10 views
63

Wracając do Scali po okresie pisania Haskell, zacząłem za pomocą słowa kluczowego typu, aby moje definicje klas nieco bardziej czytelny, np:Scala typ kluczowe: jak najlepiej wykorzystać go w wielu klasach

type RestfulParams = Map[String, String] 
def canonicalize(params: RestfulParams): String = { ... } 

Kłopot, który napotykam, polega na tym, że definicje tego typu muszą żyć wewnątrz klasy lub przedmiotu - nie są "obywatelami pierwszej klasy", tak jak w Haskell. Jeśli spróbuję zdefiniować typ poza klasą lub obiektem, otrzymam kompilator expected class or object definition.

Mój problem polega na tym, jak używać tych typów w wielu klasach i obiektach w pakiecie? Co mam zrobić teraz wydaje się dość brzydki:

object RestfulTypes { type RestfulParams = Map[String, String] etc } 

A potem w innym pliku klasy:

import utils.{RestfulTypes => RT} 
def get(resource: String, params: RT.RestfulParams): String = { ... } 

istnieje ładniejszy sposób to zrobić - a przy okazji nie guru Scala myślę, że to dobry rzecz czy coś złego, że typy można definiować tylko wewnątrz klas/obiektów?

+9

Dlaczego nie 'import utils.RestfulTypes._'? – soc

Odpowiedz

66

Czy dla Ciebie będzie pracować package objects?

Z artykułu:

Aż 2,8, tylko rzeczy można umieścić w opakowaniu były zajęcia, cechy i samodzielne obiekty. Są to zdecydowanie najczęstsze definicje, które są umieszczone na najwyższym poziomie pakietu, ale Scala 2.8 nie ogranicza cię tylko do tych. Każdy rodzaj definicji, którą możesz umieścić w klasie, możesz również umieścić na najwyższym poziomie pakietu. Jeśli masz jakąś metodę pomocniczą, którą chciałbyś mieć w zasięgu całej paczki, możesz ją umieścić na samym górze paczki. Aby to zrobić, umieść definicje w obiekcie pakietu. Każdy pakiet może mieć jeden obiekt pakietu. Wszelkie definicje umieszczone w obiekcie pakietu są uważane za elementy samego pakietu.

Istnieje już wiele typów i wartości, więc myślę, że możesz użyć tej samej techniki dla swoich własnych typów.

11

Nie jestem pewien, co stanowi uprzejmość w tym przypadku, ale są tu dwie opcje:

używając cechę: (Scala's Selfless Trait Pattern)

trait RestfulTypes { 
    type Params = Map[String,String] 
    //... 
} 

object MyRestService extends RestService with RestfulTypes { /* ... */ } 

Albo po prostu importować członków obiektu, skutecznie go używać jak opakowania:

import util.RestfulTypes._ 
+1

@agilesteel: link nie powinien być pierwszy, ponieważ należy do pierwszej opcji, nie zmieniaj znaczenia mojej odpowiedzi podczas edycji. –

+0

Dzięki, bezinteresowny wzór cech jest bardzo fajny. Zdaję sobie sprawę, że widziałem różne frameworki Scala i narzędzia, które go używały, po prostu nie zdawałem sobie sprawy z tego, co to było. Jeszcze raz dziękuję za odpowiedź. –

+0

@Kim: sry, nie powtórzy się. – agilesteel

7

Youn można użyć obiektu opakowania i umieścić deklarację typu tam. Podczas importowania tego pakietu będzie dostępna definicja typu.

Przykład:

//package myType 
package object myType {type mine = List[String]} 

Zauważ, że obiekt pakiet ma taką samą nazwę jak opakowaniu w celu być użyteczny bez obiektu prefiks tj myType.mine Jeśli nazwać go pod inną nazwą, na przykład :

//package myType 
package object mainType {type mine = List[String]} 

można uzyskać dostęp za pomocą mainType.kopalnia podczas importowania "pakiet"

aby uzyskać więcej informacji: http://www.scala-lang.org/docu/files/packageobjects/packageobjects.html

Powiązane problemy