2010-08-03 4 views
75

Quali sono gli oggetti pacchetto, non tanto il concetto ma il loro utilizzo?Oggetti pacchetto

Ho cercato di ottenere un esempio di lavoro e l'unica forma ho avuto modo di lavorare è stato il seguente:

package object investigations { 
    val PackageObjectVal = "A package object val" 
} 

package investigations { 

    object PackageObjectTest { 
     def main(args: Array[String]) { 
      println("Referencing a package object val: " + PackageObjectVal) 
     } 
    } 
} 

Le osservazioni che ho fatto finora sono:

package object _root_ { ... } 

è consentita (che è ragionevole),

package object x.y { ... } 

non consentito.

Sembra che un oggetto pacchetto debba essere dichiarato nel pacchetto padre immediato e, se scritto come sopra, è richiesto il modulo di dichiarazione del pacchetto delimitato.

Sono di uso comune? Se é cosi, come?

+6

http://www.naildrivin5.com/scalatour/wiki_pages/PackageObjects – oluies

+1

@Brent, questa è una grande risorsa, non solo per l'articolo dell'oggetto pacchetto. Ho sentito l'autore ma non mi ero reso conto che aveva scritto questo tour alla Scala, grazie. –

risposta

113

Normalmente si dovrebbe mettere il vostro oggetto di pacchetto in un file separato chiamato package.scala nel pacchetto che corrisponda. Puoi anche utilizzare la sintassi del pacchetto nidificato, ma è piuttosto insolito.

Il caso d'uso principale per gli oggetti pacchetto è quando sono necessarie definizioni in varie posizioni all'interno del pacchetto e all'esterno del pacchetto quando si utilizza l'API definita dal pacchetto. Ecco un esempio:

// file: foo/bar/package.scala 

package foo 

package object bar { 

    // package wide constants: 
    def BarVersionString = "1.0" 

    // or type aliases 
    type StringMap[+T] = Map[String,T] 

    // can be used to emulate a package wide import 
    // especially useful when wrapping a Java API 
    type DateTime = org.joda.time.DateTime 

    type JList[T] = java.util.List[T] 

    // Define implicits needed to effectively use your API: 
    implicit def a2b(a: A): B = // ... 

} 

Ora le definizioni interne che oggetto del pacchetto sono disponibili all'interno l'intero pacchetto foo.bar. Inoltre le definizioni vengono importate quando qualcuno al di fuori di quel pacchetto importa foo.bar._.

In questo modo è possibile evitare di richiedere al client API di emettere importazioni aggiuntive per utilizzare la libreria in modo efficace - ad es. in scala-swing è necessario scrivere

import swing._ 
import Swing._ 

di avere tutta la bontà come onEDT e conversioni implicite Tuple2-Dimension.

+12

Parola di cautela: l'overloading del metodo non funziona negli oggetti pacchetto. – retronym

+0

Mi colpisce perché è stato scelto che l'oggetto pacchetto debba essere definito a un livello nella gerarchia dei pacchetti. Per esempio. ciò significa che è necessario inquinare il pacchetto di livello superiore virtuale 'org' o' com' con l'oggetto pacchetto se si desidera che appartenga al proprio pacchetto radice, ad es. 'Org.foo'. Trovo che consentire alla definizione di essere direttamente sotto il pacchetto di cui dovrebbe fare parte - sarebbe stata un'interfaccia API linguistica un po 'più corretta. – matanster

7
+0

@Alex Cruise, grazie, sembra suggerire che hanno bisogno di un'unità di compilazione separata (che forse aggira la restrizione delimitata del pacchetto di parentesi graffe). Il problema è che desidero qualche solido consiglio dell'utente piuttosto che una mia congettura su come usarli. –

51

Mentre la risposta di Moritz è azzeccata, un'altra cosa da notare è che gli oggetti pacchetto sono oggetti. Tra le altre cose, questo significa che puoi crearli dai tratti, usando l'ereditarietà mix-in. L'esempio di Moritz potrebbe essere scritto come

package object bar extends Versioning 
          with JodaAliases 
          with JavaAliases { 

    // package wide constants: 
    override val version = "1.0" 

    // or type aliases 
    type StringMap[+T] = Map[String,T] 

    // Define implicits needed to effectively use your API: 
    implicit def a2b(a: A): B = // ... 

} 

Qui versioni è un tratto astratto, che dice che l'oggetto del pacchetto deve avere un metodo "versione", mentre JodaAliases e JavaAliases sono i tratti concreti contenenti tipo alias a portata di mano. Tutti questi tratti possono essere riutilizzati da molti diversi oggetti del pacchetto.

+0

L'intero argomento si sta aprendo molto e sembra essere utilizzato per il suo pieno potenziale, grazie per un altro ricco esempio. –

+1

ma non possono essere usati come vals, quindi non sono realmente oggetti –