alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Scala example source code file (ClassManifest.scala)

This example Scala source code file (ClassManifest.scala) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Scala tags/keywords

anyref, array, boolean, classmanifest, classmanifest, classtypemanifest, int, int, jclass, jclass, list, optmanifest, optmanifest, set

The Scala ClassManifest.scala source code

/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2007-2011, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */

package scala.reflect

import scala.collection.mutable.{ WrappedArray, ArrayBuilder }
import java.lang.{ Class => JClass }

/** A ClassManifest[T] is an opaque descriptor for type T.
 *  It is used by the compiler to preserve information necessary
 *  for instantiating Arrays in those cases where the element type
 *  is unknown at compile time.
 *
 *  The type-relation operators make an effort to present a
 *  more accurate picture than can be realized with erased types,
 *  but they should not be relied upon to give correct answers.
 *  In particular they are likely to be wrong when variance is
 *  involved or when a subtype has a different number of type
 *  arguments than a supertype.
 */
trait ClassManifest[T] extends OptManifest[T] with Equals with Serializable {
  /** A class representing the type U to which T would be erased. Note
    * that there is no subtyping relationship between T and U. */
  def erasure: JClass[_]
  
  private def subtype(sub: JClass[_], sup: JClass[_]): Boolean = {
    def loop(left: Set[JClass[_]], seen: Set[JClass[_]]): Boolean = {
      left.nonEmpty && {
        val next = left.head
        val supers = next.getInterfaces.toSet ++ Option(next.getSuperclass)
        supers(sup) || {
          val xs = left ++ supers filterNot seen
          loop(xs - next, seen + next)
        }
      }
    }
    loop(Set(sub), Set())
  }
  
  private def subargs(args1: List[OptManifest[_]], args2: List[OptManifest[_]]) = (args1 corresponds args2) {
    // !!! [Martin] this is wrong, need to take variance into account
    case (x: ClassManifest[_], y: ClassManifest[_]) => x <:< y
    case (x, y)                                     => (x eq NoManifest) && (y eq NoManifest)
  }

  /** Tests whether the type represented by this manifest is a subtype 
    * of the type represented by `that' manifest, subject to the limitations
    * described in the header.
    */
  def <:<(that: ClassManifest[_]): Boolean = {    
    // All types which could conform to these types will override <:<.
    def cannotMatch = {
      import Manifest._
      that.isInstanceOf[AnyValManifest[_]] || (that eq AnyVal) || (that eq Nothing) || (that eq Null)
    }

    // This is wrong, and I don't know how it can be made right
    // without more development of Manifests, due to arity-defying
    // relationships like:
    //
    //   List[String] <: AnyRef
    //   Map[Int, Int] <: Iterable[(Int, Int)]
    // 
    // Given the manifest for Map[A, B] how do I determine that a
    // supertype has single type argument (A, B) ? I don't see how we
    // can say whether X <:< Y when type arguments are involved except
    // when the erasure is the same, even before considering variance.
    !cannotMatch && {
      // this part is wrong for not considering variance
      if (this.erasure == that.erasure)
        subargs(this.typeArguments, that.typeArguments)
      // this part is wrong for punting unless the rhs has no type
      // arguments, but it's better than a blindfolded pinata swing.
      else
        that.typeArguments.isEmpty && subtype(this.erasure, that.erasure)
    }
  }
  
  /** Tests whether the type represented by this manifest is a supertype 
    * of the type represented by `that' manifest, subject to the limitations
    * described in the header.
    */
  def >:>(that: ClassManifest[_]): Boolean =
    that <:< this
  
  def canEqual(other: Any) = other match {
    case _: ClassManifest[_]  => true
    case _                    => false
  }
 
  /** Tests whether the type represented by this manifest is equal to
    * the type represented by `that' manifest, subject to the limitations
    * described in the header.
    */
  override def equals(that: Any): Boolean = that match {
    case m: ClassManifest[_] => (m canEqual this) && (this.erasure == m.erasure)
    case _                   => false
  }
  override def hashCode = this.erasure.##

  protected def arrayClass[T](tp: JClass[_]): JClass[Array[T]] = 
    java.lang.reflect.Array.newInstance(tp, 0).getClass.asInstanceOf[JClass[Array[T]]]

  def arrayManifest: ClassManifest[Array[T]] = 
    ClassManifest.classType[Array[T]](arrayClass[T](erasure))

  def newArray(len: Int): Array[T] =
    java.lang.reflect.Array.newInstance(erasure, len).asInstanceOf[Array[T]]

  def newArray2(len: Int): Array[Array[T]] =
    java.lang.reflect.Array.newInstance(arrayClass[T](erasure), len)
      .asInstanceOf[Array[Array[T]]]

  def newArray3(len: Int): Array[Array[Array[T]]] =
    java.lang.reflect.Array.newInstance(arrayClass[Array[T]](arrayClass[T](erasure)), len)
      .asInstanceOf[Array[Array[Array[T]]]]

  def newArray4(len: Int): Array[Array[Array[Array[T]]]] =
    java.lang.reflect.Array.newInstance(arrayClass[Array[Array[T]]](arrayClass[Array[T]](arrayClass[T](erasure))), len)
      .asInstanceOf[Array[Array[Array[Array[T]]]]]

  def newArray5(len: Int): Array[Array[Array[Array[Array[T]]]]] =
    java.lang.reflect.Array.newInstance(arrayClass[Array[Array[Array[T]]]](arrayClass[Array[Array[T]]](arrayClass[Array[T]](arrayClass[T](erasure)))), len)
      .asInstanceOf[Array[Array[Array[Array[Array[T]]]]]]

  def newWrappedArray(len: Int): WrappedArray[T] =
    // it's safe to assume T <: AnyRef here because the method is overridden for all value type manifests 
    new WrappedArray.ofRef[T with AnyRef](newArray(len).asInstanceOf[Array[T with AnyRef]]).asInstanceOf[WrappedArray[T]]
  
  def newArrayBuilder(): ArrayBuilder[T] = 
    // it's safe to assume T <: AnyRef here because the method is overridden for all value type manifests
    new ArrayBuilder.ofRef[T with AnyRef]()(this.asInstanceOf[ClassManifest[T with AnyRef]]).asInstanceOf[ArrayBuilder[T]]

  def typeArguments: List[OptManifest[_]] = List()

  protected def argString = 
    if (typeArguments.nonEmpty) typeArguments.mkString("[", ", ", "]")
    else if (erasure.isArray) "["+ClassManifest.fromClass(erasure.getComponentType)+"]"
    else ""
}

/** The object ClassManifest defines factory methods for manifests.
 *  It is intended for use by the compiler and should not be used
 *  in client code.
 */
object ClassManifest {
  val Byte    = Manifest.Byte
  val Short   = Manifest.Short
  val Char    = Manifest.Char
  val Int     = Manifest.Int
  val Long    = Manifest.Long
  val Float   = Manifest.Float
  val Double  = Manifest.Double
  val Boolean = Manifest.Boolean
  val Unit    = Manifest.Unit
  val Any     = Manifest.Any
  val Object  = Manifest.Object
  val AnyVal  = Manifest.AnyVal
  val Nothing = Manifest.Nothing
  val Null    = Manifest.Null

  def fromClass[T](clazz: JClass[T]): ClassManifest[T] = clazz match {
    case java.lang.Byte.TYPE      => Byte.asInstanceOf[ClassManifest[T]]
    case java.lang.Short.TYPE     => Short.asInstanceOf[ClassManifest[T]]
    case java.lang.Character.TYPE => Char.asInstanceOf[ClassManifest[T]]
    case java.lang.Integer.TYPE   => Int.asInstanceOf[ClassManifest[T]]
    case java.lang.Long.TYPE      => Long.asInstanceOf[ClassManifest[T]]
    case java.lang.Float.TYPE     => Float.asInstanceOf[ClassManifest[T]]
    case java.lang.Double.TYPE    => Double.asInstanceOf[ClassManifest[T]]
    case java.lang.Boolean.TYPE   => Boolean.asInstanceOf[ClassManifest[T]]
    case java.lang.Void.TYPE      => Unit.asInstanceOf[ClassManifest[T]]
    case _                        => classType[T with AnyRef](clazz).asInstanceOf[ClassManifest[T]]
  }

  def singleType[T <: AnyRef](value: AnyRef): Manifest[T] = Manifest.singleType(value)

  /** ClassManifest for the class type `clazz', where `clazz' is
    * a top-level or static class.
    * @note This no-prefix, no-arguments case is separate because we
    *       it's called from ScalaRunTime.boxArray itself. If we
    *       pass varargs as arrays into this, we get an infinitely recursive call
    *       to boxArray. (Besides, having a separate case is more efficient)
    */
  def classType[T <: AnyRef](clazz: JClass[_]): ClassManifest[T] =
    new ClassTypeManifest[T](None, clazz, Nil)

  /** ClassManifest for the class type `clazz[args]', where `clazz' is
    * a top-level or static class and `args` are its type arguments */
  def classType[T <: AnyRef](clazz: JClass[_], arg1: OptManifest[_], args: OptManifest[_]*): ClassManifest[T] =
    new ClassTypeManifest[T](None, clazz, arg1 :: args.toList)

  /** ClassManifest for the class type `clazz[args]', where `clazz' is
    * a class with non-package prefix type `prefix` and type arguments `args`.
    */
  def classType[T <: AnyRef](prefix: OptManifest[_], clazz: JClass[_], args: OptManifest[_]*): ClassManifest[T] =
    new ClassTypeManifest[T](Some(prefix), clazz, args.toList)

  def arrayType[T](arg: OptManifest[_]): ClassManifest[Array[T]] = arg match {
    case NoManifest => Object.asInstanceOf[ClassManifest[Array[T]]]
    case m: ClassManifest[_] => m.asInstanceOf[ClassManifest[T]].arrayManifest
  }
  
  /** ClassManifest for the abstract type `prefix # name'. `upperBound' is not
    * strictly necessary as it could be obtained by reflection. It was
    * added so that erasure can be calculated without reflection. */
  def abstractType[T](prefix: OptManifest[_], name: String, clazz: JClass[_], args: OptManifest[_]*): ClassManifest[T] =
    new ClassManifest[T] {
      def erasure = clazz
      override val typeArguments = args.toList
      override def toString = prefix.toString+"#"+name+argString
    }

  /** ClassManifest for the abstract type `prefix # name'. `upperBound' is not
    * strictly necessary as it could be obtained by reflection. It was
    * added so that erasure can be calculated without reflection.
    * todo: remove after next boostrap
    */
  def abstractType[T](prefix: OptManifest[_], name: String, upperbound: ClassManifest[_], args: OptManifest[_]*): ClassManifest[T] =
    new ClassManifest[T] {
      def erasure = upperbound.erasure
      override val typeArguments = args.toList
      override def toString = prefix.toString+"#"+name+argString
    }
}

/** Manifest for the class type `clazz[args]', where `clazz' is
  * a top-level or static class. */
private class ClassTypeManifest[T <: AnyRef](
  prefix: Option[OptManifest[_]], 
  val erasure: JClass[_], 
  override val typeArguments: List[OptManifest[_]]) extends ClassManifest[T]
{
  override def toString = 
    (if (prefix.isEmpty) "" else prefix.get.toString+"#") + 
    (if (erasure.isArray) "Array" else erasure.getName) +
    argString
}

Other Scala examples (source code examples)

Here is a short list of links related to this Scala ClassManifest.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.