Nan Jiang
Nan Jiang

Reputation: 1314

Scala: abstract class constructor parameter vs Trait val members?

I notice that there were several discussions about how to choose between abstract classes and traits, but it seems that none of them focused on the following point. One reason that made me use abstract classes is, they can have constructor parameters, while traits cannot. But why not the following

trait X {
  def haha: Int
}
class Y(val haha: Int) extends X

and early definition is even not necessary to get everything work properly (which I worried about). The abstract class version is

abstract class X(haha: Int)
class Y(val haha: Int) extends X(haha)

and I don't like the abstract class version because, when you extend several times, these constructor parameters appear everywhere (maybe someone tells me how to avoid this?).

I am aware that abstract classes interpolate with Java better, and match the "is-a" concept more. Despite these, is there any reason that I should use abstract classes somewhere? Thanks!

Upvotes: 8

Views: 10699

Answers (1)

som-snytt
som-snytt

Reputation: 39577

The class parameter does not have to be a member (field or def).

abstract class X(haha: Int) {
  val hoho = 2 * haha  // compile-time constant
}

Similarly, trait initialization order depends on linearization (mix-in order), which is why trait members should be defs and not vals. (And you can always override the def with a val.) With an abstract class, you know who your supers are, and you're defining extension points for subclasses.

But note your abstract class has the val in the wrong place:

abstract class X(val haha: Int)
class Y(haha: Int) extends X(haha)

That is, you would expect X to decide if the param is a val (and it doesn't have to be). Usage of the param in either X or Y could turn it into a field.

Your observation about value params for classes also applies to type params: What a nuisance to pass Foo[A] up the hierarchy. So in Scala, we can have a member type A instead that can remain abstract until defined in a leaf. But this doesn't actually bear on whether to define a trait or a class.

But trait parameters are coming to Scala. (See the Scala bugs for early definitions which are low-priority for this reason.)

Upvotes: 9

Related Questions