Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
865 views
in Technique[技术] by (71.8m points)

inheritance - When to use val or def in Scala traits?

I was going through the effective scala slides and it mentions on slide 10 to never use val in a trait for abstract members and use def instead. The slide does not mention in detail why using abstract val in a trait is an anti-pattern. I would appreciate it if someone can explain best practice around using val vs def in a trait for abstract methods

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

A def can be implemented by either of a def, a val, a lazy val or an object. So it's the most abstract form of defining a member. Since traits are usually abstract interfaces, saying you want a val is saying how the implementation should do. If you ask for a val, an implementing class cannot use a def.

A val is needed only if you need a stable identifier, e.g. for a path-dependent type. That's something you usually don't need.


Compare:

trait Foo { def bar: Int }

object F1 extends Foo { def bar = util.Random.nextInt(33) } // ok

class F2(val bar: Int) extends Foo // ok

object F3 extends Foo {
  lazy val bar = { // ok
    Thread.sleep(5000)  // really heavy number crunching
    42
  }
}

If you had

trait Foo { val bar: Int }

you wouldn't be able to define F1 or F3.


Ok, and to confuse you and answer @om-nom-nom—using abstract vals can cause initialisation problems:

trait Foo { 
  val bar: Int 
  val schoko = bar + bar
}

object Fail extends Foo {
  val bar = 33
}

Fail.schoko  // zero!!

This is an ugly problem which in my personal opinion should go away in future Scala versions by fixing it in the compiler, but yes, currently this is also a reason why one should not use abstract vals.

Edit (Jan 2016): You are allowed to override an abstract val declaration with a lazy val implementation, so that would also prevent the initialisation failure.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...