2014-11-06 73 views
1

我有以下代码:阶:定义一个特征类型的任何一个变量

import scala.reflect.runtime.{universe => ru} 

case class OutputAnnotation() extends scala.annotation.StaticAnnotation 

trait SimpleTrait { 

    var probe: Any 

    def outputs(): List[String] = { 
     val ouputs: List[String] = Nil 
     outputs 
    } 
} 

class WorldProbe { 
    @OutputAnnotation 
    var population: Int = 0 

    @OutputAnnotation 
    var gdp: Float = 0 

    var notIntersting: String = "" 
} 

class World extends SimpleTrait { 
    var probe: Any = new WorldProbe 
} 

object Test { 
    def main(args: Array[String]) { 
     var w: World = new World 
     var outp = w.outputs() 
    } 
} 

的想法是有一些类,所有实现某种特质,SimpleTrait,应该要求他们定义一个变量Type ... hmm的探针,类型不是真的,因为实现SimpleFeature的每个类都将带有它自己的探针类型。因此,我可以在SimpleTrait中进行探测的唯一类型是Any。给定的代码编译,但在运行时执行导致stackoverflow错误。 在附注上,我想从probe类中获取所有使用输出注释注释的变量。我怎么能这样做?

谢谢!

+1

堆栈溢出是仅仅是因为你拼错了'VAL ouputs'(而不是'outputs'),这使得第二线实际调用相同的方法递归地广告vitam aeternam。 – sjrd 2014-11-06 21:29:51

回答

3

你可以用一个抽象的类型是这样的

trait Sim { 
    type Probe 
    var probe: Probe 
} 

class WorldProbe 

class World extends Sim { 
    type Probe = WorldProbe 
    var probe: Probe = new WorldProbe 
} 
+0

谢谢,这工作:) – 2014-11-06 13:50:47

3

你的堆栈溢出是因为你outputs方法做到这一点。出于某种原因,编译器不抓取变量outputs,而是递归调用该方法。下面是具体解决:

def outputs(): List[String] = { 
    Nil 
} 

在结构方面我宁愿看到SimpleTrait有一个通用的参数,像这样:

trait SimpleTrait[T] { 
    var probe: T 

    def outputs(): List[String] = Nil 
} 

class World extends SimpleTrait[WorldProbe] { 
    var probe: WorldProbe = new WorldProbe 
} 

以及寻找你的@OutputAnnotation的所有实例,有几个的东西。 1)使用Java Annotations而不是Scala Annotations(每个人都这样做)。

import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 

@Retention(RetentionPolicy.RUNTIME) 
public @interface OutputAnnotation { 
} 

然后2)使用杰克逊的Annotation Introspector来轻松地查找和吐出值。

object Test { 
    def main(args: Array[String]): Unit = { 
    import scala.collection.JavaConversions._ 
    import com.fasterxml.jackson.databind.introspect.{AnnotatedClass, JacksonAnnotationIntrospector} 

    val x = new WorldProbe 

    val introspector = new JacksonAnnotationIntrospector 
    val ac = AnnotatedClass.construct(x.getClass, introspector, null) 

    val outFields = ac.fields().filter(_.hasAnnotation(classOf[OutputAnnotation])) 
    for (field <- outFields) { 
     field.fixAccess() 
     println(field.getName + " => " + field.getValue(x)) 
    } 
    } 
} 

其中产量这个输出:

population => 0 
gdp => 0.0 
相关问题