首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么scala不允许在特征中定义lazy val?

Scala不允许在特征中定义lazy val的主要原因是特征的混入顺序不确定性。特征是Scala中一种重用代码的机制,可以被类以及其他特征混入。lazy val是一种惰性求值的方式,在首次访问时才会计算值,并在后续访问时直接返回已计算的值。然而,特征的混入顺序是不确定的,这就导致了lazy val的初始化可能会出现问题。

考虑以下示例:

代码语言:txt
复制
trait A {
  lazy val x: Int = 1
  def printX(): Unit = {
    println(x)
  }
}

trait B {
  lazy val x: Int = 2
}

class C extends A with B

val c = new C
c.printX()

在上述示例中,类C混入了特征A和B,它们都定义了一个名为x的lazy val。由于特征混入的顺序是不确定的,因此无法确定最终使用的x的值。根据示例中的混入顺序,如果特征A先于特征B被混入,那么x的值将是1;反之,如果特征B先于特征A被混入,那么x的值将是2。这种不确定性会导致程序的行为不可预测。

为了避免这种不确定性,Scala禁止在特征中定义lazy val。如果需要在特征中延迟计算值,可以考虑使用def定义一个无参数方法,并在需要时进行调用。

值得注意的是,Scala中仍然可以在类中定义lazy val,并且在类的继承层次结构中,父类的lazy val会被正确地初始化和共享。这是因为在类中,继承的关系是确定的,不存在特征混入顺序的不确定性。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Kotlin、Swift、Scala 的延迟求值

Scala 的延迟求值 Scala 当中 lazy 是个关键字。而相比之下, Kotlin 当中我们提到 Lazy 是指类型,提到 lazy,则是指构造 Lazy 对象的高阶函数。...Kotlin 当中的 Lazy 用在定义属性时,只支持只读属性或变量上(也就是 val 修饰的属性或变量),这一点 Scala 的用法比较类似,下面是一个比较无聊的例子,不过倒是能说明问题: [Scala...哇,这样看起来 Scala 使用 lazy 关键字定义属性的语法比起 Kotlin 要简单多了哎!不过换个角度,乍一看明明有一行代码放在前面却没有立即执行是不是会很怪呢?...不支持把传名参数声明为变长参数,那么我们就换个其他类型,巧就巧 Scala 还支持类型隐式转换,所以定义一个 BooleanByName 即可,这样我们调用 assertAllTrue 传的参数就可以是...BooleanByName 的 valueByName 是一个函数,Scala 当中对于不修改类内部状态的无参函数通常声明成没有括号的样子,这样的函数调用时如同访问属性一样( 如代码的 _.valueByName

1.7K20

Scala学习笔记(一)

一、变量 获取变量的值是一个耗时的工作时,可以考虑使用lazy var. lazy val forLater = someTimeConsumingOperation() 二、函数定义 ?...这我们思考一下为什么会出现这种样式的方法调用,应该说这是用于引入了“操作符做方法名”而产生的一种自然需要!实际上,scala中允许使用操作符做方法名基本上与C++的操作符重载是一样的! ?...对于给数组赋值的语句:array(0) = “This”,这里要说明的是:不同于java的array[0] = “This” scala,[]永远是用来制定参数类型的!...模式匹配,示例二: 在下面的这个例子展示了scala一些内置的预定义的Pattern,专门应用于case上的,例如下面例子的:f,s, rest ? 模式匹配,示例三: ?...这个表述如果再深入地一想,那么我们就可以想到:所有的构造函数一开始就会首先调用主函数!!这也是为什么scala对写在Class内的零星的脚本和代码片段的处理是通过移到主构造函数内去执行的原因!

61310
  • Scala的基础概念

    Scala环境的搭建 安装Jdk6以上,并安装ScalaScala基础语法 变量修饰符 val 定义 immutable variable 常量 var 定义 mutable variable...变量 lazy val 惰性求值的常量 定义时不用显示的说明类型,scala会自己进行变量推导 前两种定义定义时表达式就会立即求值...lazy val REPLscala会给没有变量名的变量自动取值resN,可以直接引用已有的resN 注意: scala不允许常量定义后被直接改变,而变量var可以 val x...= 10 x = 20 //会报错reassignment to val val x = 20 //正确的重新赋值,需要使用val重新定义 对于lazy val,注意没有...lazy var,一般是定义惰性求值的表达式 val l = 常量或变量组成的表达式 Scala的类体系 Any 所有类的父类 AnyVal 值类型 NumericTypes

    73130

    作为Scala语法糖的设计模式

    Pavel Fatin比较的设计模式,部分模式Scala不过是一种语法糖(Syntax Sugar),包括: Factory Method Lazy Initialization Singleton...Scala,通过引入伴生对象(Companion Object)来简化静态工厂方法,语法更加干净,体现了Scala精简的设计哲学。...Scala,若未明确声明,所有函数都是严格求值的,即函数会立即对它的参数进行求值。而如果对val变量添加lazy修饰符,则Scala会延迟对该变量求值,直到它第一次被引用时。...如果要定义非严格函数,可以将函数设置为by name参数。 scalalazy修饰符常常被用作定义一些消耗资源的变量。这些资源初始化时并不需要,只有调用某些方法时,才需要准备好这些资源。...例如在Spark SQL的QeuryExecution类,包括optimizedPlan、sparkPlan、executedPlan以及toRdd等,都被定义lazy val: class QueryExecution

    1K50

    2021年大数据常用语言Scala(四):基础语法学习 声明变量

    语法格式 Java变量定义 int a = 0; scala,可以使用val或者var来定义变量,语法格式如下: val/var 变量标识:变量类型 = 初始值 其中 val定义的是不可重新赋值的变量...NOTE] scala定义变量类型写在变量名后面 scala的语句最后不需要添加分号 解释器定义一个变量 示例:定义一个变量保存一个人的名字"tom" 步骤 打开scala解释器 定义一个字符串类型的变量用来保存名字...TIP] 优先使用val定义变量,如果变量需要被重新赋值,才使用var 使用类型推断来定义变量 Scala的语法要比Java简洁,我们可以使用一种更简洁的方式来定义变量。...惰性赋值 企业的大数据开发,有时候会编写非常复杂的SQL语句,这些SQL语句可能有几百行甚至上千行。这些SQL语句,如果直接加载到JVM,会有很大的内存开销。如何解决?...语法格式: lazy val/var 变量名 = 表达式 示例 程序需要执行一条以下复杂的SQL语句,我们希望只有用到这个SQL语句才加载它。

    36520

    scala快速入门系列【变量】

    语法格式 Java 变量定义 int a = 0; scala,可以使用 val 或者 var 来定义变量,语法格式如下: val/var 变量标识:变量类型 = 初始值 其中 val定义的是不可重复赋值的变量...NOTE】 需要注意的是 scala定义变量类型写在变量名后面 scala的语句最后不需要添加分号 ---- 解释器定义一个变量 示例: 定义一个变量保存一个人的名字 “tom” 步骤:...name = "Jim" 很自然的发现报错了,因为我们在上面一个步骤创建变量name时使用的是val,而val定义的变量无法进行二次赋值(有点类似于Java的final)。...---- 惰性赋值 企业的大数据开发,有时候会编写非常复杂的SQL语句,这些SQL语句可能有几百行甚至上千 行。这些SQL语句,如果直接加载到JVM,会有很大的内存开销。如何解决?...语法格式: lazy val/var 变量名 = 表达式 示例: 程序需要执行一条以下复杂的SQL语句,我们希望只有用到这个SQL语句才加载它。

    28320

    带你快速掌握Scala操作———(1)

    退出解释器 scala命令提示窗口中执行:quit,即可退出解释器 2、声明变量 语法格式 Java变量定义 int a = 0; scala,可以使用val或者var来定义变量,语法格式如下:...val/var 变量标识:变量类型 = 初始值 其中  val定义的是不可重新赋值的变量  var定义的是可重新赋值的变量  scala定义变量类型写在变量名后面  scala的语句最后不需要添加分号...惰性赋值 企业的大数据开发,有时候会编写非常复杂的SQL语句,这些SQL语句可能有几百行甚至上千行。这些SQL语句,如果直接加载到JVM,会有很大的内存开销。如何解决?...语法格式: lazy val 变量名 = 表达式 参考代码 scala> lazy val sql = """insert overwrite table adm.itcast_adm_personas...语法 val/var 变量名 = s"${变量/表达式}字符串" 定义字符串之前添加s 字符串,可以使用${}来引用变量或者编写表达式 示例 若干个变量,分别保存:“zhangsan”、30、“

    51040

    Scala学习一

    一、scala的方法 1.Scala中方法的格式 def 方法名(参数名:参数类型,参数名:参数类型):[return type]={//方法体} 省略条件: 1.参数列表的参数类型不能省略 2.参数值类型可以省略...类似java的延迟加载。同时lazy不能修饰var类型的变量。...例如想延迟调用则 //定义方法 def getSum(a:Int, b:Int)= a + b //使用惰性方法 lazy val sum = getSum(1,2); //调用是才会加载getSum...()方法 printIn("sum: " + sum) 3.Scala的方法参数 默认参数、带名参数、变长参数 默认参数: //定义方法,同时带默认值 def getSum(x:Int = 10 ,...打印结果 printIn("result: "+ result) //50 Scala的方法与函数: 方法是属于类或者对象的,在运行时,它是加载到JVM的方法区,而函数则是加载到JVM的堆内存,同时可以将函数对象赋值给一个变量

    39921

    基于 flink 的电商用户行为数据分析【7】| 页面广告分析

    src/main/scala下创建AdStatisticsByGeo.scala文件。...同样由于没有现成的数据,我们定义一些测试数据,放在AdClickLog.csv,用来生成用户点击广告行为的事件流。 ?...代码我们首先定义源数据的样例类AdClickLog,以及输出统计数据的样例类CountByProvince。...实际场景,同一用户确实可能反复点开同一个广告,这也说明了用户对广告更大的兴趣;但是如果用户一段时间非常频繁地点击广告,这显然不是一个正常行为,有刷点击量的嫌疑。...[Long]("count",classOf[Long])) // 定义一个标识位,用来表示用户是否已经黑名单 lazy val isSendState:ValueState[Boolean

    75910

    Scala 【 4 参数、过程以及数组 Array 和 ArrayBuffer 】

    比如上面的传递 val s = sum(1 to 10) 这样子是不对的,此时需要使用 scala 特殊的语法将参数定义为序列,让 scala 解释器能够识别。...过程、lazy值和异常 过程: scala 定义函数时,如果函数体直接包括花括号里面,而没有使用 = 连接,则函数的返回值类型就是 Unit 。这种的函数被称为过程。...定义的时候不会被进行计算,有点像操作系统假分配,只有使用的时候才会去进行计算,将结果返回。 即使定义lazy 值计算会出错,但是只是定义的话不会出错,使用的才会去验证会不会出错。...scala 的 Array 代表的含义与 Java 类似,也是长度不可改变的数组。...由于 Scala 与 Java 都是运行在 JVM ,双方可以互相调用,因此 Scala 数组的底层实际上是 Java 数组。

    37830

    Scala专题系列(二):Scala控制结构

    而在Scala,几乎所有构造出来的语法结构都有值,从而使得程序更加精简,易读 1 :条件表达式 Scalaif/else 语法结构和java,C++一样,不过,Scalaif/else表达式有值...1 : 0 那么这个scala中就是val s = if(x >0 ) 1 else -1 Scala,每个表达式都有一个类型,比如上面你的表达式返回类型是int类型,因为两个分支都是int类型的...,但是如果两个分支的类型不同,那么最终返回的就是Scala的超类Any,AnyScala是所有类型的超类 val res = if(n > 0) "result" else 1 比如上面的一条语句...值得注意的是,使用原括号时, 早前版本的 Scala 要求表达式之间必须使用分号。 4 : 懒值(lazy) 当val被声明为lazy时,那么该变量的初始化将被推迟,直到我们首次对它取值。...例如 lazy val words = scala.io.Source.fromFile("/usr/local/dic/words").mkString 上面我们定义了一个lazy 的words,如果我们在后面的程序中一直没有调用

    41920

    当谈论引用透明时,我们在说什么

    (本文都以Scala进行举例) 测试1: 判断 method 是否引用透明 def method(input: Int): Int = input // One val value = method(...例子3和例子2使用了相同的表达式和值,为什么例子2不是引用透明的,但例子3就是引用透明的了呢?...因此,函数式编程,使expression pure很难,函数时的最终目的是compose所有的表达式,入口处执行唯一最终组装出来的内容,要让大expression是纯的,就需要保证每一个子expression...FP的开发过程,在做函数定义时首先要进行设计,使函数本身是引用透明的,同时注意不能相信其他部分例如入参是引用透明的,所以需要某种方式限制入参是引用透明的。...=> 改进first round:将入参变lazy,同时保证自己是引用透明的 def method(input: () => Int): () => Int = input // One val value

    30910

    Scala语法介绍

    //声明常量 val v2=200 3.懒值 Lazy     当val被声明为lazy时,它的初始化将被推迟,直到我们首次对它取值。懒值对于开销较大的初始化语句而言十分有用。     ...lazy只能用于常量(val),不能用于变量(var)。     正常情况下通过val和var定义的量都会直接分配空间,即使这个量要在很久以后才使用,这样就会造成内存空间白白被占用。     ...val name = "zhang"//直接分配空间 即使一时半会用不到 lazy val name = "zhang"//并不会立即分配空间 直到后续用到了才会分配 示例: lazy val v2=100...scala以上基本数据类型区别于其他类的地方在于,他们的对象都已直接量的形式体现。     以上基本数据类型的直接量和java基本完全相同,不再复述。     ...scala的操作符其实是普通方法调用的另一种表现形式。对以上基本的运算符的使用其实就是隐含的调用对应的方法。

    1.2K50

    ScalaPB(1): using protobuf in akka

    akka中使用自定义序列化方法包括下面的这些步骤: 1、.proto文件对消息类型进行IDL定义 2、用ScalaPB编译IDL文件并产生scala源代码。...这些源代码包括了涉及的消息类型及它们的操作方法 3、akka程序模块import产生的classes,然后直接调用这些类型和方法 4、按akka要求编写序列化方法 5、akka的.conf文件里...actor.serializers段落定义akka的默认serializer 下面的build.sbt文件里描述了程序结构: lazy val commonSettings = Seq( name...:= "AkkaProtobufDemo", version := "1.0", scalaVersion := "2.12.6", ) lazy val local = (project...", ) lazy val local = (project in file(".")) .settings(commonSettings) .settings( libraryDependencies

    1.6K30
    领券