3
votes

I'm a relatively new Scala user and I wanted to get an opinion on the current design of my code.

I have a few classes that are all represented as fixed length Vector[Byte] (ultimately they are used in a learning algorithm that requires a byte string), say A, B and C. I would like these classes to be referred to as A, B and C elsewhere in the package for readability sake and I don't need to add any extra class methods to Vector for these methods. Hence, I don't think the extend-my-library pattern is useful here. However, I would like to include all the useful functional methods that come with Vector without having to 'drill' into a wrapper object each time. As efficiency is important here, I also didn't want the added weight of a wrapper.

Therefore I decided to define type aliases in the package object:

package object abc {
    type A: Vector[Byte]
    type B: Vector[Byte]
    type C: Vector[Byte]
}

However, each has it's own fixed length and I would like to include factory methods for their creation. It seems like this is what companion objects are for. This is how my final design looks:

package object abc {
    type A: Vector[Byte]
    object A {
        val LENGTH: Int = ...
        def apply(...): A = {
            Vector.tabulate...
        }
    }
    ...
}

Everything compiles and it allows me to do stuff like this:

val a: A = A(...)
a map {...} mkString(...)

I can't find anything specifically warning against writing companion objects for type aliases, but it seems it goes against how type aliases should be used. It also means that all three of these classes are defined in the same file, when ideally they should be separated.

  1. Are there any hidden problems with this approach?
  2. Is there a better design for this problem?

Thanks.

1

1 Answers

4
votes

I guess it is totally ok, because you are not really implementing a companion object.

If you were, you would have access to private fields of immutable.Vector from inside object A (like e.g. private var dirty), which you do not have.

Thus, although it somewhat feels like A is a companion object, it really isn't.

If it were possible to create a companion object for any type by using type alias would make member visibility constraints moot (except maybe for private|protected[this]).

Furthermore, naming the object like the type alias clarifies context and purpose of the object, which is a plus in my book.

Having them all in one file is something that is pretty common in scala as I know it (e.g. when using the type class pattern).

Thus: No pitfalls, I know of. And, imho, no need for a different approach.