A defdapat diimplementasikan oleh a def, a val, a lazy valatau an object. Jadi ini adalah bentuk paling abstrak untuk mendefinisikan anggota. Karena sifat biasanya antarmuka abstrak, mengatakan Anda menginginkan a valberarti mengatakan bagaimana implementasi harus dilakukan. Jika Anda meminta a val, kelas pelaksana tidak dapat menggunakan def.
A valdiperlukan hanya jika Anda membutuhkan pengenal yang stabil, misalnya untuk tipe yang bergantung pada jalur. Itu adalah sesuatu yang biasanya tidak Anda butuhkan.
Membandingkan:
trait Foo { def bar: Int }
object F1 extends Foo { def bar = util.Random.nextInt(33) }
class F2(val bar: Int) extends Foo // ok
object F3 extends Foo {
lazy val bar = {
Thread.sleep(5000)
42
}
}
Jika Anda punya
trait Foo { val bar: Int }
Anda tidak akan bisa mendefinisikan F1atau F3.
Oke, dan untuk membingungkan Anda dan jawab @ om-nom-nom — menggunakan abstrak valdapat menyebabkan masalah inisialisasi:
trait Foo {
val bar: Int
val schoko = bar + bar
}
object Fail extends Foo {
val bar = 33
}
Fail.schoko
Ini adalah masalah buruk yang menurut pendapat pribadi saya harus hilang di versi Scala mendatang dengan memperbaikinya di kompiler, tapi ya, saat ini ini juga merupakan alasan mengapa seseorang tidak boleh menggunakan abstrak val.
Sunting (Jan 2016): Anda diizinkan untuk mengganti valdeklarasi abstrak dengan lazy valimplementasi, sehingga akan mencegah kegagalan inisialisasi.