Class Linearization in Scala

Scala Traits 实战:线性化、混入与生产级横切抽象 Scala Traits 是融合面向对象与函数式编程的核心机制,其本质远超 Java 接口——它支持状态(val/var)、具体实现、初始化逻辑及受控的多继承。关键原理在于编译器强制的线性化(Linearization)规则,确保 super 调用链唯一可预测;而混入(Mixin)机制则实现能力的结构化组合,避免抽象类单继承限制。这种设计赋予 Traits 独特的技术价值:既保障大型系统中横切关注点(如幂等、锁、可观测性)的高复用与低耦合,又要求开发者直面字段初始化顺序、this 引用泄漏、并发共享等真实工 阅读详情

Scala has a wealth of language constructs that support modern object-oriented programming. Class Linearization stands in the heart of its object model. Section 12.6 in Artima's Programming Scala is an invaluable resource. Section 7.5 in Oreilly's Programming Scala also provides a succint explaination, though its full content is not freely available online. In this article, I will try to explain what Class Linearization is and how to make it speak for our design rather than have it get in the way.

Let's start with Multiple Inheritance. Whether MI is bad is an unsettled debate(for example: http://programmers.stackexchange.com/questions/218458/is-there-any-real-reason-multiple-inheritance-is-hated). Some languages like Java opt for single inheritance and interfaces to provide some functionalities of MI(http://en.wikipedia.org/wiki/Multiple_inheritance). E.g.

class ButtonClass extends WidgetClass 
  implements ColorInterface, EffectInterface

An obvious shortcoming of this approach is that since no implementations are allowed in interfaces, the deriving class has to implement everything which is against code reuse. Java offers abstract class that could have implementation, but at the end of day it's still a class hence is restricted to be extended only.

The desire of having interfaces that contain implementation leads us to trait(another solution is mixin http://stackoverflow.com/questions/925609/mixins-vs-traits). Class Linearization is really the magic behind Scala's object model that weaves classes and traits altogether. A little bit pedantic description:

...inheritance hierarchy forms a directed, acyclic graph (see [ScalaSpec2009]). The term linearization refers to the algorithm used to "flatten" this graph for the purposes of resolving method lookup priorities, constructor invocation order, binding of super, etc.
~ Programming Scala

In short, Class Linearization flattens types in a DAG to a linear hierarchy. I'll try to visualize what it means. The syntax of trait and class roughly looks like this:

trait T [extends (C | T) (with T)*] [body]
class C [extends (C | T) (with T)*] [body]

class linearization

  • The construct/initialize order follows the linearized hierarchy from top to bottom. E.g. in the figure, C1, T2, C2, T3, T1, then CA.

  • The mixed class in which trait/class A mixes is everything from the top util A in the linearized hierarchy. E.g. T3 mixes in "C1 >: T2 >: C2".

  • When trait A extends class/trait B, it implies that the mixed class in which we mix A must be a subclass of B. To put it another way, B must appear somewhere above A in the linearized hierarchy. Therefore, trying the example of CB would give the following error.

    scala> class CB extends C2 with T1 with T3 with T4
    <console>:14: error: illegal inheritance; superclass C2
    is not a subclass of the superclass C3
    of the mixin trait T4
    
  • In addition, if we see trait A { self: B => ...}:

    trait B { val bar = "B" }
    trait A { self: B =>
    val foo = self.bar
    }
    

    It implies the concrete class must be a subclass of B. That is, B must appear anywhere in the linearized hierarchy. We should be careful about object construction/initialization. Becase if B appears below A in the linearized hierarchy, A's initialization that reads uninitialized B's feilds would get nothing.

// init/construct order: B -> A -> $anon$
scala> val c = new B with A
c: B with A = $anon$1@2efe33c7
scala> c.foo
res0: String = B
scala> c.bar
res1: String = B    
// init/construct order: A -> B -> $anon$
scala> val d = new A with B
c: A with B = $anon$1@9904c66
scala> d.foo
res2: String = null  // *nothing*
scala> d.bar
res3: String = B
  • Lastly, Scala also gives us abstract override. If I abstract override T1's "bar" in "trait T2 extends T1", the mixed class in which T2 mixes must have overriden this method too and I'll need it in my version of "bar".
    trait T1 {
    def foo: String = "T1 "
    def bar: String
    }
    trait T2 extends T1 {
    // 'super.foo' can be safely accessed since it already has a "default" definition in T1(which could be overriden by the mixed class).
      override def foo = "T2 " + super.foo
    // 'super.bar' has not defined from T2's perspective. Adding "abstract" to make sure the mixed class must have defined it. abstract override def bar = "T2 " + super.bar } class C1 extends T1 { override def foo = "C1 " + super.foo def bar = "C1 " }
    class linearization
    // T1 >: C1 >: T2 >: $anon$
    scala> val c1 = new C1 with T2
    c1: C1 with T2 = $anon$1@6e39dcd1
    scala> c1.foo
    res0: String = "T2 C1 T1 "
    scala> c1.bar
    res1: String = "T2 C1 "
    

That's what I undertand so far about Scala's Class Linearization. Please take a pinch of salt and feel free to point out any incorrect information.

【信息科学与工程学】计算机科学与自动化——第二十四篇 编译器10——编译原理与词法分析02 链接时优化:全局DCE(579)、LTO(580)安全编译:CFI(581、586)、ASan(582)、UBSan(583)、MSan(584)、TSan(585)、CET(587)、PAC(588)、MTE(589)、SFI(590)、Wasm沙箱(591)侧信道与秘密:侧信道缓解(592)、常量时间(593)、秘密清理(594)内存安全:ASLR(595)、栈保护(596)、整数溢出检测(597)、除零检测(598)、空指针检测(599)、数组边界检查(600)至此编号达到600。 阅读详情

相关推荐

改进差分进化算法及其求解柔性作业车间调度问题(Python代码实现)

内容概要:本文系统探讨了改进差分进化算法在求解柔性作业车间调度问题中的应用,并结合Python代码实现,展示了该算法相较于传统方法在全局搜索能力和收敛速度方面的优势。研究不仅聚焦于算法本身的改进策略,如变异、交叉和选择操作的优化,还深入分析了其在复杂制造环境中应对多目标、多约束调度问题的有效性。文中通过标准测试实例验证了算法性能,并与其他智能优化算法进行了对比分析,体现了其在实际工程应用中的潜力。此外,文档还关联了多无人机路径规划、电力系统状态估计、微电网优化、图像与信号处理等多个前沿技术领域,展现了智能优化算法在跨学科工程仿真与决策支持中的广泛适用性。; 适合人群:具备一定编程基础和工程背景,从事智能制造、自动化、工业工程、电气工程、控制科学与工程、计算机科学及相关领域的科研人员、高校研究生及企业研发技术人员。; 使用场景及目标:①为科研工作者提供可复现的智能优化算法代码框架,支持柔性作业车间调度、多无人机协同路径规划、电力系统优化等复杂工程问题的建模仿真;②辅助完成学术论文复现、课程设计、毕业设计或科研项目开发;③推动智能算法在生产调度、能源管理、交通规划等实际场景中的落地应用。; 阅读建议:建议读者结合文中提供的算法原理与代码实现,动手调试并验证不同参数设置对优化结果的影响,同时可参考荔枝科研社提供的完整资源包进行扩展学习与实践,以加深对算法机制与工程应用的理解。

scala的linearization

《Programming in scala,3rd Edition》chapter12.6后,尝试自己绘制了下linearization 书本示例中除了最后的Cat的申明用了with,其他的trait/class都只有extends,即单一继承。 这里构造了相对复杂的情况来说明linearization是怎样的。 [code="java"] class Animal ...

yangbb的专栏 246

复现基于改进秃鹰算法的微电网群经济优化调度研究(Matlab代码实现)

内容概要:本文聚焦于“基于改进秃鹰算法的微电网群经济优化调度”研究,提出一种改进的秃鹰优化算法(IBOA)以解决传统智能优化算法在求解过程中易陷入局部最优、收敛速度慢等问题。通过引入自适应权重、动态搜索机制及种群多样性保持策略,显著增强了算法的全局搜索能力和收敛精度。研究构建了包含光伏发电、风力发电、储能系统、可控负荷及电网交互的微电网群多主体协同调度模型,以系统综合运行成本最小化为目标函数,综合考虑功率平衡、设备出力能力、储能荷电状态、爬坡速率等多种实际约束条件。利用Matlab平台进行仿真验证,并与标准BOA、PSO、GA等经典智能算法进行对比,结果表明所提算法在降低系统运行成本、提高可再生能源消纳率及优化调度效率方面具有明显优势。; 适合人群:适用于具备电力系统基础、优化理论知识及Matlab编程能力的高校研究生、科研人员及从事微电网、综合能源系统优化调度相关工作的工程技术人员。; 使用场景及目标:①用于微电网群或多微网系统的经济调度建模与仿真;②开展新型智能优化算法的设计、改进与性能评估;③支撑含高比例可再生能源的配电系统优化运行决策; 阅读建议:建议结合提供的Matlab代码深入理解算法实现细节与调度模型构建过程,重点分析改进策略对优化性能的影响,并可通过替换场景参数或引入其他算法进行横向对比实验,进一步掌握智能优化在能源系统中的应用方法。【复现】基于改进秃鹰算法的微电网群经济优化调度研究(Matlab代码实现)

scala linearization

scala linearization for super callscala initialization order is reverse of linearization 

zjfzjf2012的博客 191

【Ultrascale+ MPSOC学习记录】10、PS端以太网使用lwip

还是参考ALINX教程,学习PS端以太网如何使用,从教程中可以看到,开发板使用了一个xilinx默认不支持的phy JL2121,所以需要修改lwip的库源码。

ryo891012的博客 880

ipsec 加密流程(一):ipsec策略匹配

《openswan》专栏系列文章主要是记录openswan源码学习过程中的笔记。 Author: Toney Email: vip_13031075266@163.com Date: 2020.11.22 Copyright: 未经同意不得转载!!! Version:2.6.51.5 Reference:https://download.openswan.org/openswan/ 1. ipsec策略匹配流程(ipsec_tunnel_start_xmit) 注:open...

遇见你是我最美丽的意外 9121

SCALA学习笔记(一)

变量 获取变量的值是一个耗时的工作时,可以考虑使用lazy var. lazy val forLater = someTimeConsumingOperation() scala> val first :: rest = List(1, 2, 3) first: Int = 1 rest: List[Int] = List(2, 3) 函数定义 “=”并不只是

Laurence的技术博客 2万+

保姆级教程:用达芬奇Configurator配置CAN总线(从DBC导入到Controller设置)

本文详细介绍了使用达芬奇Configurator工具从DBC文件导入到CAN总线控制器设置的全流程配置方法。通过环境准备、CAN控制器模式选择、硬件参数配置、通信参数优化及通信栈集成等关键步骤,帮助开发者高效完成AUTOSAR架构下的CAN总线开发,特别适合汽车电子领域的工程师参考。

weixin_30529023的博客 441

深入理解Scala默认参数函数:从方法重载到优雅API设计

我写这篇文章的时候,特意没罗列默认参数有多少种用法——因为用法很简单,谁都能写。默认参数为什么重要?可选参数。Java里你想要可选参数?写重载方法。想要几个?写一堆。代码臃肿,维护痛苦。Scala的默认参数把这件事简化了——一行函数签名,编译器帮你生成所有的重载方法。调用方想用默认值就用默认值,想改哪个就改哪个,不用管顺序。把重复的事情交给编译器,让程序员专注在业务逻辑上。你不用手写重载方法——编译器帮你写。你不用记参数顺序——命名参数帮你记。你不用写Builder类——默认参数就是Builder。

https://starzy1990.github.io/ 743

手把手拆解固态电池成本:2030年真能比液态电池便宜30%吗?

本文深度解析固态电池成本结构,探讨2030年实现比液态电池便宜30%的可行性路径。通过拆解正极材料、负极材料和固态电解质的成本演变,分析关键技术对降本的影响,并预测产业链协同效应下的成本优化趋势。文章指出,在材料创新、设备国产化和政策支持等多重因素推动下,固态电池有望在2030年实现显著降本目标。

kite3的博客 401

如何利用CN3791实现太阳能电池板对锂电池的高效充电管理

本文详细介绍了如何利用CN3791芯片实现太阳能电池板对锂电池的高效充电管理。CN3791集成了MPPT(最大功率点跟踪)功能,能智能调节太阳能板的输出,确保在不同光照条件下获得最大功率。文章涵盖芯片工作原理、外围电路设计、充电全过程管理及实际应用经验,帮助开发者优化太阳能充电系统效率。

weixin_33709219的博客 499

深入理解Scala嵌套函数:作用域封装之道

我写这篇文章的时候,特意没罗列嵌套函数有多少种写法——因为写法很简单,谁都能写。嵌套函数为什么重要?辅助逻辑的作用域应该是多大?Java里你写辅助逻辑,只能写到类级别——因为Java的方法必须定义在类级别。但很多辅助逻辑其实只属于某一个函数,不属于整个类。你把它们写到类级别,就造成了作用域放大——本来应该是函数内部的东西,变成了类级别的东西。Scala的嵌套函数把这个问题解决了——辅助逻辑可以精确地封装在主函数内部。它直接访问外层函数的变量,不用把上下文传来传去。它不暴露到类级别,不造成API膨胀。

https://starzy1990.github.io/ 732

Python 爬虫进阶:爬取 APP 数据(Charles 抓包 + Requests)

本文详细介绍了APP数据爬取的完整技术方案。首先通过Charles抓包工具配置HTTPS代理和证书,解析APP通信协议;然后分析请求参数、反爬机制和动态签名生成规则;接着使用Python的Requests库实现模拟请求、分页爬取和数据存储;最后针对证书问题、Token失效等常见问题提供解决方案。文章强调抓包分析、参数逆向和请求模拟三大核心技术,同时提醒开发者需遵守法律法规,合理控制爬取频率。该方案适用于移动端数据采集场景,为无法直接获取网页数据的情况提供了有效解决方案。

2503_91057718的博客 2120

深入理解Scala可变参数函数:从Java数组语法到优雅集合传递

我写这篇文章的时候,特意没罗列可变参数有多少种用法——因为用法很简单,谁都能写。Scala的可变参数为什么比Java好用?不是因为它有:_*这个语法——而是因为它的底层是Seq,不是数组。Java的可变参数是数组的语法糖——你传List进去,它不认,因为List不是数组。你想传?自己转。Scala的可变参数是Seq的语法糖——你传任何序列进去,只要用:_*展开就行。不用转,不用强转,一行代码搞定。**这就是函数式语言的设计哲学:可变参数不是"数组的便捷写法",它是"序列的便捷写法"。

https://starzy1990.github.io/ 438

Zookeeper+Hadoop+Spark+Flink+Kafka+Hbase+Hive 完全分布式高可用集群搭建(保姆级超详细含图文) 附安装包网盘下载

Hadoop+Spark+Flink+Zookeeper+Kafka+Hbase+Hive完全分布式高可用集群搭建 Hadoop高可用集群搭建 Spark高可用集群搭建 Flink高可用集群搭建 Zookeeper高可用集群搭建 Kafka高可用集群搭建 Hbase高可用集群搭建 Hive高可用集群搭建 mysql搭建 jdk部署 大数据集群环境搭建

Mr.L-OAM的博客 2万+

【数据分析】基于多组学数据整合的微生物与宿主互作网络构建及可视化分析

综上所述,本教程通过详细的步骤和方法,展示了如何整合微生物群落数据、宿主基因表达数据和代谢组数据,构建微生物与宿主互作网络,并进行可视化分析。这种方法为研究微生物与宿主之间的复杂关系提供了一种有力的工具,有助于推动相关疾病的研究和治疗。然而,在实际应用中,需要注意数据处理和分析过程中的各种问题,并结合实验验证来提高研究结果的可靠性和科学性。未来,随着多组学技术的不断发展和完善,以及数据分析方法的创新,相信我们能够更深入地理解微生物与宿主之间的互作机制,为疾病的预防、诊断和治疗提供更有力的支持。

专注生信领域 370

深入理解Scala Map:从实现原理到工程实践

我写这篇文章的时候,特意没罗列Map有多少个方法——因为那些东西官方文档都有,查一下就行。Map到底解决了什么问题?它不是"带key的列表",它是一个"从key到value的映射函数"。它用哈希表的O(1)查找,换来了通过key快速找到value的能力。在大数据开发里,Map无处不在——维度关联、配置映射、计数统计、分组聚合、缓存索引。理解了Map,你就理解了大数据处理里最核心的几个操作:查找、映射、聚合。很多人用了几年Map,还停留在"new一个HashMap,然后put put put"的阶段。

https://starzy1990.github.io/ 389

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

深入理解Scala匿名函数:函数式编程基石

我写这篇文章的时候,特意没罗列匿名函数有多少种写法——因为写法很简单,谁都能写。匿名函数为什么是函数式编程的基石?把函数当参数传。你不能把函数当参数传,就没有map、filter、reduce这些集合操作。没有这些集合操作,就没有声明式编程。没有声明式编程,就没有函数式编程。Java花了很长时间才意识到这一点——Java 8才加了Lambda。但Java的Lambda是不完整的——它只能捕获final变量,不能修改变量。它是一个"阉割版"的闭包。Scala呢?

https://starzy1990.github.io/ 500

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Scala List操作:不可变链表的函数式美学

Scala的List,表面上是Java List的"Scala版",本质上是函数式编程的核心数据结构——不可变的链表,配合模式匹配和递归,构成了声明式数据处理的基础。天然线程安全:不可变对象不需要锁,在多线程环境下可以安全共享结构共享:操作List时可以复用大部分结构,性能更好函数式友好:map/filter/reduce不修改原List,可以组合、可以嵌套这些特性不是孤立的,它们共同支撑了Scala的函数式编程范式。

https://starzy1990.github.io/ 1334

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

【Spark】 04键值对 RDD:创建、常用操作与数据分区

介绍 Spark 键值对 RDD 的创建方式、聚合、分组、连接、排序与行动操作,并结合 PageRank 示例讲解数据分区、分区器复用与自定义分区方式。

qq_46126258的博客 368

大数据Spark(八十二):Spark 算子综合案例

本文通过四个典型Spark算子应用案例,系统讲解了单词频次过滤、PV/UV统计、二次排序及分组取TopN的实现方法。涵盖flatMap、mapToPair、reduceByKey、distinct、sortByKey、groupByKey等核心算子的组合使用,提供Java与Scala双语言实现,兼顾可读性与实用性。强调根据数据规模选择合适方案,避免内存溢出,适用于大数据处理场景的实战参考。

Lansonli(蓝深李)的博客 612

深入理解Scala递归函数:从栈溢出到尾调用优化

我写这篇文章的时候,特意没罗列递归有多少种写法——因为递归的语法很简单,谁都能写。为什么Java的递归会栈溢出,而Scala的不会?不是因为Scala更厉害——而是因为Scala是函数式语言,递归是它的核心特性之一。它从设计之初就考虑了尾调用优化的问题。Java是命令式语言,它的核心是对象和方法,递归只是一个"能用但不推荐"的特性。Java程序员写递归:栈溢出,不敢用Scala程序员写递归:尾递归,随便写递归不是洪水猛兽,栈溢出是因为你没写对。你可以用递归的优雅写法,获得循环的性能。

https://starzy1990.github.io/ 612

深入理解Scala可变Map:动态构建场景下的性能与设计权衡

我写这篇文章的时候,特意没罗列可变Map有多少个方法——因为那些东西官方文档都有,查一下就行。为什么需要可变Map?不是因为"它就是Java HashMap的Scala版",而是因为在动态构建数据的场景下,不可变Map的性能不够好。你要在循环里不断往Map里加key-value对,用不可变Map就是O(n²)的灾难,用可变Map就是O(n)的高效。但可变Map也不是万能的。它只适合"构建"场景——你在一个方法内部,动态构建一个Map,最后输出一个不可变Map。

https://starzy1990.github.io/ 360

深入理解Scala元组:从多返回值到模式匹配的桥梁

函数式编程里,函数的参数和元组是一一对应的。在函数式编程里,一个函数可以看成是接收一个参数、返回R的函数。这个叫"函数的元组化"(tupled)。而Scala的类型系统在处理多参数函数的时候,需要为每个参数数量生成对应的函数类型——、…、。因为函数最多到Function22,所以元组也最多到Tuple22。这是一个统一的设计——元组和函数,共享同一个N的上限。那22以上怎么办?用嵌套元组或者case class。// 超过22个元素:用嵌套。

https://starzy1990.github.io/ 693

深入理解Scala函数定义:从方法到函数的类型跨越

最常用的方式。定义一个方法,属于当前类/对象。name特点:有名字、有参数类型、有返回类型(可以省略,编译器推断)、函数体用连接。定义一个函数值,它是一个对象,可以到处传。name特点:用val定义(因为它是值),参数和返回类型写在括号里,=>后面是函数体。我写这篇文章的时候,特意没罗列函数有多少种写法——因为那些语法东西,查文档就有。Scala为什么要有函数这个概念?不是因为"函数式编程嘛,函数是一等公民"——这句话说了等于没说。当你需要对一组数据做变换的时候,你需要一个"可以传进去的操作"。

https://starzy1990.github.io/ 689

大数据Spark(八十三):Spark中的分区器Partitioner介绍

本文介绍Spark中Partitioner的作用及三种实现方式:HashPartitioner(基于哈希取模,默认分区器,高效但易倾斜)、RangePartitioner(按键范围分区,支持排序,数据均衡性好)和自定义分区器(按业务规则分配,灵活应对特殊需求)。合理选择分区器可优化shuffle性能,提升作业效率。

Lansonli(蓝深李)的博客 573
上一篇: Scala: Linearization technique to avoid multiple inheritance
下一篇: Mahout – Clustering (聚类篇)
DViewer
博客等级 码龄16年 16粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值