sergeda
sergeda

Reputation: 2221

Scala how to pass Object type to type parameter?

I've defined class like this:

class Counta [T : TypeTag] {
--cutted--
}

And I need at runtime instantiate this class with correct type. I have function that create correct type of object at runtime:

  def ConvertSparkTypesToScala(dataType: DataType) = {
    dataType match {
      case IntegerType => Int
      case BooleanType => Boolean
      case FloatType => Float
      case DoubleType => Double
      case LongType => Long
      case ByteType => Byte
      case ShortType => Short
    }
  }

Now when I try to instantiate class like this:

      val scalaType = ConvertSparkTypesToScala(dt)
      println(scalaType)
      val countA = new Counta[scalaType.type]
      println(scalaType)

I get exception and only first println prints:

object scala.Int

then I got exception:

java.lang.UnsupportedOperationException: Schema for type scalaType.type is not supported

so basically this doesn't behave the same like writing type in your code. So question is, is what I want to do possible? If so, how this can be achieved?

Upvotes: 1

Views: 2463

Answers (1)

Jasper-M
Jasper-M

Reputation: 15086

Perhaps you can try something along these lines. But I'm guessing that what you are trying to do simply doesn't make a lot of sense because this is probably an XY problem.

import scala.reflect.runtime.universe._

def ConvertSparkTypesToScala(dataType: DataType): TypeTag[_] = {
  dataType match {
    case IntegerType => typeTag[Int]
    case BooleanType => typeTag[Boolean]
    case FloatType => typeTag[Float]
    case DoubleType => typeTag[Double]
    case LongType => typeTag[Long]
    case ByteType => typeTag[Byte]
    case ShortType => typeTag[Short]
  }
}

val dt: DataType = LongType
val scalaTag = ConvertSparkTypesToScala(dt)
println(scalaTag)
val countA = new Counta()(scalaTag)

countA now has the existential type Counta[_], meaning that if Counta has methods that take a T or produce a T, those methods are pretty much useless now, because the compiler doesn't know what T really is.

What you tried to do was compute information at runtime in the ConvertSparkTypesToScala method and then use that information at compile time to tell the compiler what the type countA will be. You will always compile your program before it is run, so it is not possible for information to flow from runtime to compile time.

If you want the type of countA to be computed based on dt

  1. you will need to compute it at compile time (with implicits or macros or...) and
  2. the precise type dt needs to be known at compile time; meaning the type of dt has to be LongType.type or IntegerType.type, not just DataType.

Upvotes: 1

Related Questions