何时在 Scala 特征中使用 val 或 def? [英] When to use val or def in Scala traits?

查看:38
本文介绍了何时在 Scala 特征中使用 val 或 def?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在浏览 有效的 scala 幻灯片,它在幻灯片 10 中提到永远不要使用 val 在抽象成员的 trait 中,并使用 def 代替.幻灯片没有详细提到为什么在 trait 中使用抽象的 val 是一种反模式.如果有人可以解释在抽象方法的特征中使用 val 与 def 的最佳实践,我将不胜感激

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

推荐答案

def 可以通过 defval 中的任意一个来实现>、lazy valobject.所以它是定义成员的最抽象的形式.由于特征通常是抽象接口,所以说你想要一个 val 就是说如何实现应该做的.如果您要求 val,则实现类不能使用 def.

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.

val 仅在您需要稳定标识符时才需要,例如对于路径依赖类型.这是您通常不需要的东西.

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.

比较:

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
  }
}

如果你有

trait Foo { val bar: Int }

您将无法定义 F1F3.

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

好的,让你困惑并回答@om-nom-nom——使用抽象的vals会导致初始化问题:

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!!

这是一个丑陋的问题,在我个人看来应该通过在编译器中修复它在未来的 Scala 版本中消失,但是是的,目前这也是一个不应该使用抽象 val 的原因s.

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.

编辑(2016 年 1 月):您可以使用 lazy val 实现覆盖抽象的 val 声明,这样也可以防止初始化失败.

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.

这篇关于何时在 Scala 特征中使用 val 或 def?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆