代码之家  ›  专栏  ›  技术社区  ›  Geo

Scala分配VAL

  •  22
  • Geo  · 技术社区  · 14 年前

    为什么不能这样:

    def main(args:Array[String]) {
        val whatever:String // Have it uninitialized here
    
        if(someCondition) {
            whatever = "final value" // Initialize it here
        }
    }
    

    我不明白为什么这不合法。我知道我可以做一个 var ,但为什么我们必须初始化 val 我们什么时候申报的?以后能够初始化它不是更符合逻辑吗?

    5 回复  |  直到 12 年前
        1
  •  38
  •   Nicolas Payette    14 年前

    你可以做:

      val whatever =
        if (someCondition)
          "final value"
        else
          "other value"
    
        2
  •  29
  •   Kevin Wright    14 年前

    Java解决方案实际上是解决并非所有表达式都返回值的问题的解决方案,因此您不能用Java编写:

    final String whatever = if (someCondition) {
        "final value"
    } else {
        "other value"
    }
    

    Java越来越倾向于使用三元运算符:

    final String whatever = someCondition ? "final value" : "other value"
    

    这对于有限的用例来说是好的,但是一旦开始处理switch语句和多个构造函数,就完全站不住脚了。


    Scala的方法在这里是不同的。所有对象构造最终都必须通过一个“主”构造函数,所有表达式都返回一个值(即使它是 Unit ,相当于Java的 Void ),并且强烈支持构造函数注入。这导致对象图被清晰地构建为有向无环图,并且可以很好地处理不可变对象。

    您还需要注意的是,在单独的操作中声明和定义变量通常是处理多个线程时的一种错误做法,并且可能会使您在最不期望的情况下暴露空值和竞争条件(尽管这在对象构造过程中并不是真正的问题)。不可变值的原子化创建只是函数式语言帮助处理并发性的一个方面。

    这也意味着Scala编译器可以避免Java语言规范中一些极其复杂的流分析。

    如前所述,Scala方法是:

    val whatever =
      if (someCondition)
        "final value"
      else
        "other value"
    

    val whatever = someCondition match {
      case 1 => "one"
      case 2 => "two"
      case 3 => "three"
      case _ => "other"
    }
    

    有了一点Scala的经验,你会发现这种风格有助于编译器帮助你,你应该发现自己编写的程序有更少的bug!

        3
  •  9
  •   Max A.    14 年前

    使用 lazy val 是这样的:

    def main(args:Array[String]) {
      lazy val whatever:String = if (someCondition) "final value" else "other value"
    
      // ...
    
      println(whatever) // will only initialize on first access
    }
    
        4
  •  7
  •   Alex Cruise    14 年前

    除了其他人所说的,请注意Java允许“blank final”“variables”,这是我有点怀念的特性:

    final Boolean isItChristmasYet;
    
    if (new Date().before(christmas)) {
        isItChristmasYet = Boolean.FALSE;
    } else {
        isItChristmasYet = Boolean.TRUE;
    }
    

    whatever 变量未赋值if someCondition 不成立。

        5
  •  3
  •   Jens Schauder    14 年前

    因为“val”的目的是向读取器(和编译器)发送信号: “此值将保持初始化时的值,直到它不存在为止”

    如果没有初始化,这就没有多大意义。

    当然,我们可以想出一些像val(3)这样的东西,它允许一个变量有三个赋值,但我认为这没有多大用处。