views:

119

answers:

2

I have a case class (let's name it Stuff) that I want to be able to create anonymous subclasses of at run time by extending a trait (call it Marker). Here's a snippet of a REPL session that illustrates what I'm trying to do:

scala> trait Marker
defined trait Marker

scala> case class Stuff(i: Int)
defined class Stuff

scala> val a = Stuff(1)
a: Stuff = Stuff(1)

scala> val b = new Stuff(1) with Marker
b: Stuff with Marker = Stuff(1)

Note how a is instantiated using Stuff.apply(), while in b's case I'm calling the case class' constructor.

My question is: is instantiating case classes using a constructor kosher? It appears to me that it is, since the usual conveniences provided by case classes, such as ==, .equals(), and .hashCode(), all work. Am I missing anything that would brand what I'm doing a Bad Thing (TM)?

scala> a == b
res0: Boolean = true

scala> a.equals(b)
res1: Boolean = true

scala> a.hashCode == b.hashCode
res2: Boolean = true
+3  A: 

To the question

is instantiating case classes using a constructor kosher

the answer is definitely yes. Something like

val b = new Stuff(1)

poses no problems at all. Now, new Stuff(1) with Marker is different because an anonymous subclass of Stuff is created. I believe, though, that it's still unproblematic. The problems I know about appear when case classes inherit from other case classes, and you aren't doing that. But I may be unaware of something.

EDIT: just tested matching in the REPL:

scala> val b = new Stuff(1)
b: Stuff = Stuff(1)

scala> b match {case Stuff(x) => x}
res0: Int = 1

scala> b match {case Stuff(_) => true}
res1: Boolean = true
Alexey Romanov
The only potential minor issue I see there is with pattern matching. `b` above will not match against Stuff(_), but `val c: Stuff = new Stuff(1) with Marker` will match just fine.
Max A.
It does match, see the update.
Alexey Romanov
@Alexey: I think @Max meant this: http://paste.pocoo.org/show/266270/
missingfaktor
Ah, I see now. Thought "`b` above" referred to the `b` in my reply.
Alexey Romanov
+3  A: 

Here's how Stuff.apply is implemented:

object Stuff {
  def apply(i: Int): Stuff = new Stuff(i)
}

So there's no harm at all in using new Stuff.

Daniel