Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 980
Mansur Ashraf Avatar asked Oct 28 '13 18:10

Mansur Ashraf


People also ask

What is the difference between DEF and Val in Scala?

That's all about the difference between var, val, and def in Scala. In short, the val and var are evaluated when defined, while def is evaluated on call. Also, val defines a constant, a fixed value that cannot be modified once declared and assigned while var defines a variable, which can be modified or reassigned.

What does def mean in Scala?

def is the keyword you use to define a method, the method name is double , and the input parameter a has the type Int , which is Scala's integer data type. The body of the function is shown on the right side, and in this example it simply doubles the value of the input parameter a : def double(a: Int) = a * 2 -----

In which of the given case is it appropriate to define a trait in Scala?

Traits are used to define object types by specifying the signature of the supported methods. Scala also allows traits to be partially implemented but traits may not have constructor parameters. A trait definition looks just like a class definition except that it uses the keyword trait.

Can Scala trait have variables?

In scala, trait is a collection of abstract and non-abstract methods. You can create trait that can have all abstract methods or some abstract and some non-abstract methods. A variable that is declared either by using val or var keyword in a trait get internally implemented in the class that implements the trait.


1 Answers

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.

like image 73
0__ Avatar answered Oct 14 '22 16:10

0__