Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala:获取混合了特征的类的名称_Scala_Traits - Fatal编程技术网

Scala:获取混合了特征的类的名称

Scala:获取混合了特征的类的名称,scala,traits,Scala,Traits,给定一个类的实例,我们显然可以返回其名称: trait MixedInClassDiscovery { val className = this.getClass.getName } class AClass extends MixedInClassDiscovery { ... this.className // returns "AClass" ... } 但是这种方法使用反射,对AClass的每个实例使用一次反射。是否可以对每堂课做一次同样的操作 想到的一个解决方案是将

给定一个类的实例,我们显然可以返回其名称:

trait MixedInClassDiscovery {
  val className = this.getClass.getName
}

class AClass extends MixedInClassDiscovery {
  ...
  this.className // returns "AClass"
  ...
}
但是这种方法使用反射,对
AClass
的每个实例使用一次反射。是否可以对每堂课做一次同样的操作


想到的一个解决方案是将它混合到伴随对象中,而不是类本身。

您可以使用pimp my lib模式来实现。创建从
AnyRef
到例如
ClassNameAdder
的隐式转换。但不建议在类型层次结构的这个级别创建这样的隐式转换

不管怎样,代码来了:

scala> class ClassNameAdder(ref: AnyRef) { def className = ref.getClass.getName }
    defined class ClassNameAdder

scala> implicit def anyref2classnameadder(ref: AnyRef) = new ClassNameAdder(ref: AnyRef)
anyref2classnameadder: (ref: AnyRef)ClassNameAdder

scala> "foo".className
res6: java.lang.String = java.lang.String

scala> new Object().className
res7: java.lang.String = java.lang.Object

scala> List(1,2,3).className
res8: java.lang.String = scala.collection.immutable.$colon$colon

scala> class MyClass
defined class MyClass

scala> val myClass = new MyClass
myClass: MyClass = MyClass@1398044

scala> myClass.className
res9: java.lang.String = MyClass

我想不出任何不增加额外开销的方法。但是,您可以使用伴生对象和一些额外的工作:

object Example {
  trait Discovery {
    def companion: Discovered
    def className: String = companion.className
  }
  trait Discovered extends Discovery {
    override lazy val className = {
      println("Getting class name!")  // To see how many times we're called
      this.getClass.getSuperclass.getName
    }
  }
  class Test extends Discovery {
    def companion = Test
  }
  object Test extends Test with Discovered {}
}
在这里我们看到这是可行的:

scala> val a = new Example.Test
a: Example.Test = Example$Test@17e4c97

scala> val b = a.className
Getting class name!
b: String = Example$Test

scala> val c = a.className
c: String = Example$Test

但这需要付出相当大的代价:您不仅需要用发现来装饰类,还需要实现companion方法,并为每个类编写companion对象(顺便说一句,它不需要具有相同的名称)。

不,此代码仍然对每个实例进行反射调用。实际上,对于每一个
className
调用,尽管这可以很容易地修复。