Scala: Linearization technique to avoid multiple inheritance

本文探讨了Scala中特质的概念及其如何避免多重继承的问题。通过线性化技术,Scala能够解决调用超类方法时可能出现的歧义。文章详细解释了线性化的计算过程,并通过实例展示了不同特质组合下线性化顺序的变化。

To support inheritance Scala has introduced a concept called trait almost similar to Java`s interface. But unlike Java interfaces, Scala traits can actually define any concrete methods. From this it seems apparently that Scala supports multiple inheritance; but that is not the case. To avoid multiple inheritance Scala uses a technique called linearization to flatten the calls to super classes.

 

To illustrate this linearization technique we will use some Scala classes mixed-in with Scala Traits as per the below inheritance structure:

Linearization technique

Now, say, BaseClass has a function print and each of the traits as well as the DerivedClass overrides the print function and also calls the print function of the super class. So the class/trait definitions are as follows:

Linearization technique

So the question is, if we call the print function of the DerivedClass then what will be the call flow of the print function of the super classes. (Please note that each of the overridden function in each class/traits has a call to the print function of the super class)

If Scala would have supported multiple inheritance then the above calls should create an ambiguity as we are not sure which of the print functions will get called or even whether the print function of the base class would get called thrice. But Scala avoids this ambiguity by linearization.

Scala Linearization technique uses the following equation to flatten the calls to the super classes and avoid multiple inheritance (Reference Scala Language Specification Section 5.1.2):

Linearization technique

Where +: denotes a concatenation function where elements at right hand operand replaces identical elements of the left hand operand as follows:

Linearization technique

Also C1... Cn denotes the inherited classes/traits in order they are declared for the class from left to right.

We will use our sample class hierarchy to explain the above linearization equation.

If we want to find out the linearization structure of or DerivedClass defined as

Linearization technique

then the above parameters of linearization for this DerivedClass would be:

Linearization technique

And then the linearization equation for the DerivedClass will be:

Linearization technique

Now we will apply the same equation for all other classes and traits.

So for BaseClass the definition is

Linearization technique

So the linearization equation of BaseClass would be

Linearization technique

(NOTE: Though we didn`t added any super class of BaseClass, but as per Scala hierarchy the default super class of any Scala class is scala.AnyRef, similarly scala.AnyRef extends scala.Any)

Now if we simplify this we will get the following:

Linearization technique

Applying same equation for Trait1 which is defined as:

Linearization technique

the linear form will be:

Linearization technique

Similarly for Trait2 and Trait3 we get:

Linearization technique

And

Linearization technique

So we get the following linear form of all the classes/traits:

Linearization technique

Except for the DerivedClass all other classes/traits have the linear form. Let us now use the equation to linear the DerivedClass

Linearization technique

If we simplify the above equation and apply the `+:` operation then we get the following equation:

Linearization technique

Just to explain the above simplification logic we are using the +: operation which is defined as

Linearization technique

So for,

Linearization technique

the "BaseClass, scala.AnyRef, scala.Any" of the left operand is removed since the right operand also has the same and the result is

Linearization technique

So the final linear form of the DerivedClass is:

(DerivedClass, Trait3, Trait2, Trait1, BaseClass, scala.AnyRef, scala.Any)

If we call the print function of the DerivedClass we will get the following output:

Linearization technique

This proves that when we call the print function of the DerivedClass and since each of the classes/traits has a call to super.print the call will follow the above linear sequence and thus Scala avoids multiple inheritance.

Following diagram shows the inheritance and the linearization for our sample classes/traits: enter image description here

Linearization technique

The linear form of a class hierarchy will depend on the order of the traits imported. For example if we change the definition of our DerivedClass from

Linearization technique

to

Linearization technique

and then apply the above series of equations then we will get a different linear form of our DerivedClass which will be:

Linearization technique

So the conclusion is that the definition of a trait does not define the linear form, instead how it is mixed-in with a class defines the actual linear form.

Dipta P. Banerjee


代码转载自:https://pan.quark.cn/s/133311188eb6 ### C# DllImport功能说明及路径选取问题分析 #### 一、DllImport核心原理 `DllImport`是.NET Framework内的一种技术,用于执行平台调用服务(Platform Invoke, 简称P/Invoke),该机制使得.NET应用程序能够调用非托管代码中的函数,例如Windows API或其他非托管库中的函数。这对于增强.NET应用程序的功能性非常关键,因为许多高级系统级操作(例如文件操作、进程控制等)通常由非托管库负责实现。 `DllImport`特性包含在`System.Runtime.InteropServices`命名空间中,它的主要功能是向CLR(Common Language Runtime)指示如何定位并调用非托管库中的特定函数。 #### 二、DllImport特性包含的主要元素 `DllImport`特性所包含的主要元素有: - **DllName**:必需的字符串参数,用于表明需要导入的非托管库的名称。 - **CallingConvention**:可选参数,用于设定调用协议。在默认情况下,其值为`CallingConvention.Cdecl`。 - **CharSet**:可选参数,用于定义字符集的类型。在默认情况下,其值为`CharSet.Auto`,即根据函数的签名自动决定字符集。 - **EntryPoint**:可选参数,用于指定非托管库中的函数名称。若未提供,则默认使用应用程序的方法名称作为函数名称。 - **ExactSpelling**:可选布尔值,用于确定函数名称是否必须与非托管库中的完全一致。...
代码下载链接: https://pan.quark.cn/s/8df2b016201b 555 芯片的引脚布局、功能特性、引脚示意图以及引脚说明是关键信息。555 芯片作为一种集成电路,具有多样化的功能特性,在定时器、定时延时控制、调光、调温、调压、调速等多种控制及计量检测领域有着广泛的应用。接下来将展示 555 芯片的引脚示意图和引脚说明: 1. 555 芯片引脚示意图:555 芯片包含 8 个引脚,具体如下: * 1 脚:地线端 * 2 脚:触发输入端 * 3 脚:输出端 * 4 脚:复位端 * 5 脚:控制端 * 6 脚:阈值端 * 7 脚:放电端 * 8 脚:电源端 2. 555 芯片引脚说明: * 1 脚:地线端,用于连接电路的负极部分。 * 2 脚:触发输入端,用于接收外部信号的输入,进而控制输出端的状态。 * 3 脚:输出端,输出高电平或低电平信号,其状态受触发器控制。 * 4 脚:复位端,当输入低电平时,输出端会输出低电平信号。 * 5 脚:控制端,用于调节输出端的状态,能够改变上下触发电平的数值。 * 6 脚:阈值端,作为上比较器的输入端,当输入高电平时,输出端会输出低电平信号。 * 7 脚:放电端,是内部放电管的输出端,其输出电平状态受触发器控制。 * 8 脚:电源端,用于连接电源的正极部分。 3. 555 芯片工作原理:555 芯片的工作原理是通过上比较器和下比较器来控制输出端的状态。上比较器的输入端位于 6 脚,而下比较器的输入端位于 2 脚。根据输入端的电平状态,输出端会输出高电平或低电平信号。 4. 555 芯片应用领域:555 芯片在各种电子产品中有着广泛的应用,例如在定时器、定时延时控制、调光、调温、调压、调速等领域。它还可以用于...
内容概要:本文围绕通信资源受限与恶意攻击干扰下的孤岛微电网分布式二次控制策略展开深入研究,提出了一种融合动态事件触发机制与抗拒绝服务(DoS)攻击设计的弹性控制方案。该方案旨在解决在有限通信带宽和网络攻击共存环境下,孤岛微电网面临的频率电压失稳、功率分配失效等关键问题。通过构建基于混合系统理论的协同控制模型,有效降低了通信频率以节约资源,同时增强了系统对DoS攻击的容忍能力,确保在攻击发生时仍能实现频率与电压的快速恢复及有功无功功率的精确分配。研究提供了完整的Simulink仿真模型与Matlab代码实现,通过多种复杂工况下的仿真实验,全面验证了所提策略在控制性能、通信效率、系统鲁棒性与安全弹性方面的优越性,为构建高可靠、高安全的未来微电网控制系统提供了坚实的理论依据和技术路径。; 适合人群:具备电力系统、自动控制或相关领域基础知识,从事微电网、分布式能源控制、电力电子与智能电网方向研究的研究生、科研人员及工程技术人员;熟悉Matlab/Simulink仿真工具者优先。; 使用场景及目标:①解决孤岛微电网在通信受限和网络攻击环境下频率电压失稳、功率分配失效的问题;②实现低通信开销下的高效二次控制,提升系统弹性与安全防御能力;③为相关科研项目、学位论文或工程应用提供可复现的仿真模型与算法参考。; 阅读建议:建议读者结合文中提供的Simulink仿真模型与Matlab代码进行实践操作,重点关注动态事件触发机制的设计逻辑、DoS攻击建模方法及其对系统性能的影响分析,同时按照文档目录循序渐进地学习,以全面掌握控制策略的实现细节与优化思路。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值