2

In Scala, I am doing some Java interop. I am creating a value of class Sample.Individual and I am calling a static Java method like Sample.Individual.newBuilder(). I am using a few classes that all have this same static method (eg: Sample.Position and Sample.Feature). I want to make a function that parameterizes over them, so something like:

def p[T](s: String): T = {
    val pb = T.newBuilder() // this returns a value of type T.Builder
    ... do stuff with pb ...
    pb.build() // this returns a value of type T
}

but this tells me "not found: value T"

What is the right way to parameterize the type Sample.Individual that lets me also call static methods contained in it from Scala?

2
  • Scala might have sugar for this, but it would require runtime reflection to actually implement, since it couldn't use the normal dynamic dispatch. Commented May 12, 2016 at 0:07
  • 1
    I don't think there is a direct way to do that. At least not as you demonstrated. But you can use TypeTags/ClassTags to get more information about the type being handled and then use Java Reflections API to invoke the static method. Commented May 12, 2016 at 0:55

1 Answer 1

1

I'd strongly recommend you don't go forward with this idea. Even if you find a way to do it, it's not idiomatic Scala. It's remotely possible you shave off a few lines of code, but you loose in readability and performance; bad trade-off.

The problem you're having is that you're giving your p function a type parameter T, and then invoking the newBuilder method on that type T. You can't do that, because Scala knows nothing about your type T.

Instead, first learn a little more about those Java types. Do all the potentially constructed classes extend a common type? If not, you're out of luck (you're technically not out of luck if you choose to pimp the library you're using, but please don't :P).

Otherwise, just import those types (including the generic one). Put the generic type as the type of your p function and match on the string, then just instantiate your type. Strings can be whatever, so you probably want to return an Option[GenericClass] rather than a GenericClass.

e.g.

import xxx.GenericClassBuilder
import xxx.GenericClass
import xxx.ClassA
import xxx.ClassB

def p(s: String): Option[GenericClass] = {
   val maybePb: Option[GenericClassBuilder] = s match {
      case "ClassA" => Some(ClassA.newBuilder())
      case "ClassB" => Some(ClassB.newBuilder())
      case _ => None
   }
   maybePb.foreach { pb => ... do side-effecty stuff with pb ...}
   maybePb.map(_.build())
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you. As a Scala newbie, this is the kind of stuff I need to understand, thanks for taking the time!
@prismofeverything thanks to you as well. Trying to explain things properly helps me understand it better.

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.