Reputation: 18424
I have a graph, where each vertex has both an ID (which never changes) and a label (which changes frequently). Both are represented by longs.
Currently, I define the following types:
type VertexId = Long
type VertexLabel = Long
However, I discovered a bug today where I was passing in a VertexLabel to a function that expected a VertexId. This seems like the type of thing the scala compiler should be able to prevent.
I considered doing this instead:
case class VertexId(id: Long)
case class VertexLabel(label: Long)
But then there's extra overhead of "boxing" and "unboxing" and some extra memory usage.
Is there anyway to get the best of both worlds? Define both types as Longs in such a way that the compiler will prevent you from using one as the other?
Upvotes: 3
Views: 117
Reputation: 55569
Type aliases are really just for code clarity. When you declare type VertexId = Long
, you're saying that VertexId
is equivalent to Long
. Then transitively, VertexId
is equivalent to VertexLabel
. They are still both Long
underneath, and that is how the compiler will see them once de-aliased.
So no, I don't think you can completely get the best of both worlds here, because you're requirement is that VertexId
and VertexLabel
must be different types. A simple type alias cannot do that.
@Lee's answer is correct in that you can use value classes to create different types, (most of the time) without actually instantiating the types at runtime. But note the caveats in the link.
Upvotes: 3
Reputation: 144136
Yes, you can use value classes:
case class VertexId(val id: Long) extends AnyVal
case class VertexLabel(val label: Long) extends AnyVal
see http://docs.scala-lang.org/overviews/core/value-classes.html
Upvotes: 9