prismofeverything
prismofeverything

Reputation: 9049

Accessing static methods of parameterized Java classes from Scala

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?

Upvotes: 2

Views: 134

Answers (1)

mlg
mlg

Reputation: 1511

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())
}

Upvotes: 1

Related Questions