How to check I'm inside a @specialized function or class at runtime in scala?

匿名 (未验证) 提交于 2019-12-03 08:54:24

问题:

Let's say I have a specialized class and an associated companion object:

trait Slice[@specialized +T] {     ...      override def equals(that :Any) = that match {         case s :Slice[_] => ???         case _ => false     } }  object Slice {     def newInstance[@specialized T] = ??? } 

Is there any way to check

  1. Inside a method of Slice if this instance is a specialized subclass,
  2. Inside a method of Slice if another instance is a specialized subclass for the same primitive,
  3. Inside a specialized method on a companion object if I'm running an erased or specialized variant

without resorting to ClassTags or passing Class[_] manually? It seems like that information should be available, but the only way I can think of involves checking names of the classes.

Use case 2) is particularly important, as I could resort to faster algorithms if I new I'm comparing apples with apples. It probably could be accomplished by reflection, but it would be quite tricky when you take into account that we have to handle non-synthetic subclasses of Slice, too; if we have also

trait ArraySlice[@specialized T] extends Slice[T] { ... } 

that should be considered 'compatible' with Slice[T] instances as long as they are both specialized (or both erased)?

回答1:

Ok, I figured out a cleaner way:

final val AllButUnit = new Specializable.Group((Byte, Short, Int, Long, Char, Float, Double, Boolean, AnyRef))  def specializationFor[@specialized(AllButUnit) E] :ResolvedSpecialization[E] =     Specializations(new SpecializedKey[E]).asInstanceOf[ResolvedSpecialization[E]]   private val Specializations = Seq(     resolve[Byte],     resolve[Short],     resolve[Int],     resolve[Long],     resolve[Char],     resolve[Float],     resolve[Double],     resolve[Boolean],     resolve[Unit],     resolve[AnyRef] ).map(     spec => spec.key -> spec :(SpecializedKey[_], ResolvedSpecialization[_]) ).toMap.withDefaultValue(resolve[AnyRef])  private def resolve[@specialized(AllButUnit) E :ClassTag] :ResolvedSpecialization[E] =     new ResolvedSpecialization[E](new SpecializedKey[E], new Array[E](0))   class ResolvedSpecialization[@specialized(AllButUnit) E] private[SpecializedCompanion]         (val array :Array[E], val elementType :Class[E], val classTag :ClassTag[E], private[SpecializedCompanion] val key :SpecializedKey[E]) {     private[SpecializedCompanion] def this(key :SpecializedKey[E], array :Array[E]) =         this(array, array.getClass.getComponentType.asInstanceOf[Class[E]], ClassTag(array.getClass.getComponentType.asInstanceOf[Class[E]]), key)      override def toString = s"@specialized($elementType)"      override def equals(that :Any) = that match {         case r :ResolvedSpecialization[_] => r.elementType==elementType         case _ => false     }      override def hashCode = elementType.hashCode }  private class SpecializedKey[@specialized(AllButUnit) E] {     override def equals(that :Any) = that.getClass==getClass     override def hashCode = getClass.hashCode      def className = getClass.getName     override def toString = className.substring(className.indexOf("$")+1) } 

Now specializationFor[E].elementType returns class corresponding to specialization parameter of E.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!