Declare abstract fields as paren-less methods

When declaring abstract fields in an abstract class or a trait, it’s good practice to declare them as paren-less methods.

Prefer:

abstract class Foo {
  def bar: Int
}

Over:

abstract class Foo {
  val bar: Int
}

Reason

Scala allows abstract paren-less methods to be implemented as vals, but not the other way around.

Given the following:

abstract class AsDef {
  def bar: Int
}

abstract class AsVal {
  val bar: Int
}

Implementing AsDef.bar as a val compiles:

new AsDef {
  override val bar = 0
}

But implementing AsVal.bar as a def does not:

new AsVal {
  override def bar = 0
}
// error: overriding value bar in class AsVal of type Int;
//  method bar needs to be a stable, immutable value
//   override def bar = 0
//   ^^^^^^^^^^^^^^^^^^^^

Declaring abstract fields as vals closes some possibilities, while declaring them as paren-less methods has no ill effect.

Exceptions to the rule

There’s at least one known scenario where declaring an abstract field as a val is important: path-dependent types, where its important that the field has a concrete type.

Here, for example:

trait Foo {
  val bar: String
}

val foo: Foo = new Foo {
  override val bar = "baz"
}

It’s possible to to refer explicitly to the type of foo.bar:

val fooBar: foo.bar.type = foo.bar

Had we defined bar as a def:

trait Foo {
  def bar: String
}

val foo: Foo = new Foo {
  override val bar = "baz"
}

Then we’d get a compilation error attempting to get the type of foo.bar:

val fooBar: foo.bar.type = foo.bar
// error: stable identifier required, but foo.bar.type found.
// val fooBar: foo.bar.type = foo.bar
//             ^^^^^^^^^^^^

Checked by

This rule is not checked by any linter that I know of.