jerome
jerome

Reputation: 2089

Scala object constructor

I have to create a file loader object and I would like the file to be loaded only once at object creation.
What I did until now is create a trait with a method read that will read file and output a list of String.

trait Loader {
  protected val readSource: List[String] = {
    Source
      .fromInputStream(getClass.getResourceAsStream("filename"), "UTF-8")
      .getLines()
      .toList
  }

  def transform(delimeter: String): Vector[C] = {
    val lines = readSource
    // process the lines
  }
}

The trait is implemented by several object, and the transform method can be called multiple times in the client code.

I would like to avoid re reading the file each time the transform method is called and my first solution was to extract the val lines = readSource from the transform method and make a function of it def loadFile = readSource and to create a apply method in my objects to call loadFile like so :

object MyLoader extends Loader {
  def apply: List[String] = {
    loadFile
  }
}

I am wondering if this is the right way to do it. Thank you for your advices.

Upvotes: 0

Views: 116

Answers (1)

som-snytt
som-snytt

Reputation: 39577

If you want the resource read once for all, then you should do that in a singleton object, which will be initialized once lazily.

Clients should use that object. "Prefer composition over inheritance" is the mantra.

If you want a mix-in that makes it easy to use the object, you can use "self-types" to constrain clients:

trait HasResource { val resource: R = TheResource }
trait Client { self: HasResource => def getR: R = resource }

This is the "cake pattern" way of making stuff available.

Upvotes: 1

Related Questions