Iterating through a list of companion objects


#1

I have stored some parameters in the companion objects of several classes, and I would like to be able to check and print those parameters for each companion object. In each companion object, I have defined a function called checkParameters, and I would like to iterate through such a list of companion objects and call that function for each one. But if I put them in a List (or Vector, or Set), the List type reverts to something that does not support the function call. Is there a way to do this? I could put them into a Tuple, but what should the type of the Tuple be, and how can I make it general enough for an arbitrary number of companion objects? I prefer to stick with the standard Scala library. Any ideas? Thanks.


#2

Maybe you could define a trait that defines checkParameters, and mix it into each object, then use a List of objects of the trait?


#3

Yes, that works. Thanks.

I was thinking that perhaps a structural type might work and be less intrusive, but I could not figure out the syntax.


#4

Yeah, in Haskell, I would use a typeclass. Unfortunately, Scala typeclasses have so much overhead, a trait seems like a better alternative since you just need to enforce that all your objects provide the “checkParameters” method.


#5

Structural types are great but they include runtime overhead and are not the easyest solution to work with. In general I prefer typeclasses or interfaces.

After a bit of troubles anyhow I’ve managed to make up an example with structural types.


  object A {
    def checkParameters: Int = 0
  }

  object B {
    def checkParameters: Int = 1
  }

  object C {
    def checkParameters: Int = 2
  }

  import scala.language.reflectiveCalls

  type ST = {def checkParameters: Int}

  def iterate(listObjects: List[ST]): Unit =
    listObjects.foreach(o => println(o.checkParameters))

  val a: ST =  A
  val b: ST =  B
  val c: ST =  C

  val l: List[ST] = List(a, b, c)

  iterate(l)

prints

0
1
2

#6

The shorter version

List[{ def checkParameters: Int }](A, B, C).foreach(o => println(o.checkParameters))

also works. However I don’t really see any benefit in doing this. If you define this method in a companion object, it’s just as easy to also have that object extend a trait.