1

I have a class with a generic type parameter and I would like to create an instance of this type using reflection. Moreover, the type has a private constructor. Here is a code sample of the problem:

class X private (x: Int) {
}
class Y private (y: Int) {
}
abstract class Foo[T](z : Int) {
  var bar : T = createInstance[T](z)
  def createInstance[T](z: Int) : M = {
     ???
  }
}

This would allow me to instantiate Foo and access bar:

class xFoo extends Foo[X]{
}

class yFoo extends Foo[Y]{
}

var xfoo = new xFoo(5)
println(xfoo.bar.x)

var yfoo = new yFoo(6)
println(yfoo.bar.y)

This should print out '5' and '6'.

I have tried using implicit in the following way.

def createInstance[T](z: Int)(implicit tag: TypeTag[T]) : T = {
  val clazz = tag.tpe.getClass
  val ctor = class.getDeclaredConstructor(classOf[Int])
  ctor.setAccessible(true)
  return ctor.newInstance(z).asInstanceOf[T]
}

However, then I get the error:

No TypeTag available for T

in line

var bar : T = createInstance[T](z)

Any suggestions? Thanks for your help!

2
  • I think that you should be using scala.reflect.ClassTag instead of a TypeTag. Commented Oct 19, 2016 at 10:50
  • Do you really want for createInstance to have its own T type parameter, different from Foo's? Commented Oct 19, 2016 at 16:25

1 Answer 1

1

Assuming that the super class does expose some method/value you're looking for like:

class X private(val x: Int) {}

You can extend it like so:

import scala.reflect._

class Foo[T](z : Int)(implicit ct: ClassTag[T]) {
  var bar : T = createInstance[T](z)
  def createInstance[T](z: Int) : T = {
    val ctor = ct.runtimeClass.getDeclaredConstructor(classOf[Int])
    ctor.setAccessible(true)
    ctor.newInstance(Int.box(4)).asInstanceOf[T]
  }
}

This enables you to call:

class XFoo(n: Int) extends Foo[X](n)
println((new XFoo(5)).bar.x)
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, but in the line
Thanks, but in the line val ctor = classTag[X].runtimeClass.getDeclaredConstructor(classOf[Int]) you are using classTag[X]. Shouldn't that be classTag[T]?
Sorry, I think my question was not precise enough. The abstract class Foo should serve as base class for several classes that differ in their type T: xFoo extends Foo[X] yFoo extends Foo[Y]
Fixed and updated. I'm assuming that the class you're extending does expose the method/field you're after though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.