2010-08-03 6 views
75

¿Qué son los objetos del paquete, no tanto el concepto sino su uso?Paquete de objetos

He tratado de conseguir un ejemplo de trabajo y la única forma que tengo de trabajo fue el siguiente:

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) 
     } 
    } 
} 

Las observaciones que he hecho hasta el momento son:

package object _root_ { ... } 

no está permitida (lo cual es razonable),

package object x.y { ... } 

tampoco está permitido.

Parece que un objeto de paquete debe declararse en el paquete primario inmediato y, si se escribe como arriba, se requiere el formulario de declaración de paquete delimitado por llave.

¿Son de uso común? ¿Si es así, cómo?

+6

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

+1

@Brent, este es un gran recurso, no solo para el artículo del objeto del paquete. He oído hablar del autor, pero no me di cuenta de que había escrito esta gira de Scala, gracias. –

Respuesta

113

Lo normal es que puesto que el objeto de paquete en un archivo separado llamado package.scala en el paquete que corresponde a. También puede usar la sintaxis del paquete anidado, pero eso es bastante inusual.

El caso de uso principal para objetos de paquete es cuando necesita definiciones en varios lugares dentro de su paquete, así como también fuera del paquete cuando usa la API definida por el paquete. Aquí está un ejemplo:

// 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 = // ... 

} 

ahora las definiciones dentro de ese objeto de paquete están disponibles dentro de todo el paquete foo.bar. Además, las definiciones se importan cuando alguien fuera de ese paquete importa foo.bar._.

De esta forma puede evitar que el cliente API emita importaciones adicionales para usar su biblioteca de manera efectiva, p. Ej. en Scala-swing tiene que escribir

import swing._ 
import Swing._ 

que tienen todos los beneficios como onEDT y conversiones implícitas Tuple2-Dimension.

+12

Palabra de advertencia: la sobrecarga de métodos no funciona en los objetos del paquete. – retronym

+0

Me supera el motivo por el cual se ha elegido que el objeto del paquete se defina un nivel más arriba en la jerarquía del paquete. P.ej. esto significa que debe contaminar el paquete virtual de nivel superior "org" o "com" con su objeto de paquete si desea que pertenezca a su propio paquete raíz, p. 'org.foo'. Encuentro que permitir que la definición esté directamente debajo del paquete del que debería formar parte - habría sido una interfaz de API de idioma un poco más adecuada. – matanster

7
+0

@Alex Cruise, gracias, esto parece sugerir que necesitan una unidad de compilación por separado (que quizás se salga de la restricción del paquete delimitado por el paréntesis). El problema es que quiero un consejo sólido del usuario en lugar de mi propia conjetura sobre cómo usarlos. –

51

Si bien la respuesta de Moritz es acertada, una cosa adicional a tener en cuenta es que los objetos del paquete son objetos. Entre otras cosas, esto significa que puedes crearlos a partir de los rasgos, usando la herencia mix-in. El ejemplo de Moritz podría escribir como

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 = // ... 

} 

Aquí versiones es un rasgo abstracto, que dice que el objeto de paquete debe tener un método de "versión", mientras que JodaAliases y JavaAliases son rasgos concretos que contienen alias de tipo práctico. Todos estos rasgos pueden ser reutilizados por muchos objetos de paquete diferentes.

+0

Todo el tema se está abriendo mucho y parece estar acostumbrado a todo su potencial, gracias por otro buen ejemplo. –

+1

pero no pueden usarse como vals, por lo que no son realmente objetos –

Cuestiones relacionadas