2011-03-03 10 views
16

Quiero definir algunas anotaciones y usarlas en Scala.Cómo crear anotaciones y obtenerlas en scala

Miré en la fuente de la Scala, que se encuentra en scala.annotation paquete, hay algunas anotaciones como tailrec, switch, elidable, y así sucesivamente. Así que he definido algunas anotaciones que los cumplan

class A extends StaticAnnotation 

@A 
class X { 
    @A 
    def aa() {} 
} 

Entonces escribo una prueba:

object Main { 
    def main(args: Array[String]) { 
     val x = new X 
     println(x.getClass.getAnnotations.length) 
     x.getClass.getAnnotations map { println } 
    } 
} 

Imprime algunos mensajes extraños:

1 
@scala.reflect.ScalaSignature(bytes=u1" !1* 1!AbCaE 
9"a!Q!! 1gn!!.<b iBPE*,7 
    Ii#)1oY1mC&1'G.Y(cUGCa#=S:LGO/AA!A 1mI!) 

Parece que no puedo conseguir la anotación aaa.A.

¿Cómo puedo crear anotaciones en Scala correctamente? ¿Y cómo usarlos y obtenerlos?

Respuesta

6

¿Podría tener algo que ver con la retención? Apuesto a que @tailrec no está incluido en el bytecode que se genera.

Si intento de extender ClassfileAnnotation (con el fin de presentar retención de tiempo de ejecución), Scala me dice que no se puede hacer, y tiene que ser hecho en Java:

./test.scala:1: warning: implementation restriction: subclassing Classfile does not 
make your annotation visible at runtime. If that is what 
you want, you must write the annotation class in Java. 
class A extends ClassfileAnnotation 
    ^
2

puede encontrar una buena descripción de cómo las anotaciones se van a utilizar en la Scala de Programming Scala.

Para que pueda definir o usar anotaciones en scala. Sin embargo, hay al menos una limitación:

La retención en tiempo de ejecución no es muy posible. En teoría, debe crear la subclase ClassFileAnnotation para lograr esto, pero actualmente scalac informa la siguiente advertencia si lo hace:

"restricción de implementación: subclases Classfile no hace que su anotación sea visible en tiempo de ejecución. Si eso es lo que desea, debe escribe la clase de anotación en Java ".

También significa que su código está bien tal como está (al menos tan fino como actualmente es posible en Scala), pero la anotación está en la clase solo durante el tiempo de compilación. Entonces podrías usarlo, p. en los complementos del compilador, pero no podrá acceder a él en tiempo de ejecución.

+0

¿Puede dar los números de capítulos/página en el libro? – Jus12

16

FWIW, ahora puede definir la anotación scala en scala 2.10 y usar la reflexión para volver a leerlas.

He aquí algunos ejemplos: Reflecting Annotations in Scala 2.10

+2

Gracias, muy útil. ¿Podría agregar la esencia de sus ejemplos aquí en su respuesta también? – Beryllium

+7

el enlace está roto ... – evandor

+0

@evandor +1 No funciona –

0

Con Scala 2.11.6, esto funciona para extraer valores de una anotación:

case class MyAnnotationClass(id: String) extends scala.annotation.StaticAnnotation 

val myAnnotatedClass: ClassSymbol = u.runtimeMirror(Thread.currentThread().getContextClassLoader).staticClass("MyAnnotatedClass") 
val annotation: Option[Annotation] = myAnnotatedClass.annotations.find(_.tree.tpe =:= u.typeOf[MyAnnotationClass]) 
val result = annotation.flatMap { a => 
    a.tree.children.tail.collect({ case Literal(Constant(id: String)) => doSomething(id) }).headOption 
} 
+0

¿Qué es 'u'? ¿Podría darnos un ejemplo apropiado? –

+0

u es para scala.reflect.runtime.universe –

Cuestiones relacionadas