Search code examples
scalainstantiation

Scala objects constructed inside if


I want to do something I feel is simple, but I cannot figure out the way to do it. It is the following: according to some String variable I want to create an object of some specific type. However, the underlying objects have the same methods, so I want to be able to use this object outside the if block where the object is created. What is the best possible way to achieve it?

To ilustrate my need, here is the code:

var model = null
if (modelName == "KMeans") {
  model = new KMeans()
} else if (modelName == "BisectKMeans") {
  model = new BisectingKMeans()
}
model.setK(k)
model.fit(data)

Both KMeans and BisectingKMeans have the setK and fit methods. I want to create the object inside the if block but use the object outside it. This code gives an error when declaring the variable, as I'm not initializing it.

I've tried generic objects with a case class and declaring the variable as Any type, but cannot manage to get this to work, what is the best way to achieve what I'm looking for?


Solution

  • Scala actually does allow you to do this with structural types:

    type Model = { 
      def setK(k: Int): Any
      // the links in the question don't have a fit method
      def fit(???): ???
    }
    
    val model: Model = if (modelName == "KMeans") { new KMeans() } else { model = new BisectingKMeans() }
    model.setK(k)
    model.fit(data)
    

    But it isn't particularly recommended to use if you have better alternatives due to use of reflection. I would simply call setK and fit inside the blocks in this specific case; or if not, create your own wrappers of KMeans and BisectingKMeans which implement a common trait.