Stackable Traits Pattern:方法的实现“需要‘抽象覆盖’修饰符”

2024-02-26

最近,我发现了可堆叠特征模式并遵循了所描述的示例here http://www.artima.com/scalazine/articles/stackable_trait_pattern.html。一切正常,但有一种情况我无法理解:

trait A { 
    def test : String 
}
trait B extends A { 
    // 'abstract override' modifier required as 
    // the test() method is not yet implemented
    abstract override def test = { 
        s"B${super.test}" 
    } 
}
class C extends A with B { 
    // test method concrete implementation
    override def test = { "C" } 
}

<console>:10: error: overriding method test in trait B of type => String;
method test needs `abstract override' modifiers
   class C extends A with B { override def test = { "C" } }

我不明白为什么这不能编译,以及为什么 C::test 方法需要提到的修饰符。

我注意到,为了进行编译,我可以进行两项修改,或者通过在运行时编写 C 类:

class C extends A { override def test = { "C" } }
new C with B // works as expected

或者通过添加一个额外的类(有点相同,但在编译时):

class C extends A { 
    override def test = { "C" } 
}
class D extends C with B

new D().test
res5: String = BC

为什么我需要一个额外的课程(顺便说一句,它扮演着基础班 http://www.artima.com/scalazine/articles/stackable_trait_pattern.html) ?


出现这种行为的原因是 Scala 的类线性化,它用于解决歧义和语义abstract override。但首先要说的是。

类线性化

每当你有一个实例时a类型的A然后你调用它的方法a.foobar(),编译器必须弄清楚在哪里可以找到定义foobar. Since A可以扩展任何其他类和一组特征,该函数可能有多个定义foobar。为了解决这些歧义,Scala 将对你的类进行线性化A及其所有超类和特征。线性化将产生一个顺序,在该顺序中检查不同类型的定义foobar。第一个匹配将是执行的函数。

Scala 规范将线性化定义如下

定义 5.1.2 设 C 是一个具有模板 C1 且 ... 具有 Cn { stats } 的类。 C、L(C)的线性化定义如下: L(C) = C , L(Cn)+: ... +: L(C1)

这里 +: 表示串联,其中右操作数的元素替换左操作数的相同元素。

由于所有理论都是灰色的,让我们看一个例子:

trait T1 {
  def foobar() = 1
}

trait T2 {
  def foobar() = 2
}

class B extends T2 {
  override def foobar() = 42
}

class A extends B with T1 with T2 {
  override def foobar() = super.foobar()
}

首先,我们必须重写foobar类中的方法A,因为我们对它有多个相互竞争的定义。然而,现在的问题是,调用了哪个方法定义super.foobar。为了找到这一点,我们必须计算线性化A.

L(A) = A, L(T2) +: L(T1) +: L(B)
L(B) = B, L(T2)
L(T2) = T2
L(T1) = T1
L(A) = A, T2 +: (T1, B, T2)
L(A) = A, T1, B, T2

Thus, super.foobar将调用定义T1返回1.

抽象覆盖

The abstract override方法的修饰符基本上表示必须有一个类/特征I实现此方法,该方法出现在特征之后abstract override实例化类的类线性化中的修饰符。这是执行所必需的super.foobar(), 因为super.foobar()需要进一步寻找线性化的定义foobar.

当你现在看看类的定义时C然后你会看到它具有以下线性化

 C, B, A

因此,它无法编译,因为从B你没有找到一个实现test.

当我们现在查看有效的示例时,我们就会明白为什么它们实际上有效。如果是C extends A with new C with B,你基本上创建了一个匿名类Z extends C with B。的线性化Z is

Z, B, C, A

在那里你看到了,那B可以找到C的实施test。这样,代码就可以编译了。对于类的例子也是如此D.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Stackable Traits Pattern:方法的实现“需要‘抽象覆盖’修饰符” 的相关文章

随机推荐

  • 如何对ServiceStack进行单元测试?

    我喜欢 SS 但我在尝试对我的业务层进行单元测试时摸不着头脑 我是单元测试和模拟的新手 并且一直在阅读 NSubstitute 因为这看起来像是一个有趣的模拟层 我的文件结构大致如下 MainAppHostProject AppStart
  • 使用Python解析JSON数据

    我从 GitHub Webhook 服务收到一些数据 它包含有关存储库中最近提交的信息 我收到的字符串如下所示 payload ref refs heads master commits added author username myna
  • 如何检索 Pandas 数据框中的列数?

    如何以编程方式检索 pandas 数据框中的列数 我希望有这样的事情 df num columns Like so import pandas as pd df pd DataFrame pear 1 2 3 apple 2 3 4 ora
  • Docker:运行 html 文件的基本示例 dockerfile

    docker 和 dockerfile 是否有任何非常基本且仍然可行的示例来运行单个 html 文件并在 docker 的帮助下将其显示给其他人 要在 http 上提供 html 文件 您需要一个 Web 服务器 因此要做到这一点 您需要做
  • scipy.interpolate.Rbf 的意外结果

    我在使用 RBF 进行插值时遇到一些错误 这是一维的示例 我认为这与我的 y 值彼此之间的接近程度有关 有什么解决办法吗 import numpy as np from scipy interpolate import Rbf interp
  • 从雅虎财经获取 1 分钟柱线

    我正在尝试从雅虎财经下载 1 分钟的历史股票价格 包括当天和前一天的价格 Yahoo 就像 Google 支持最多 15 天的数据 使用以下 API 查询 http chartapi finance yahoo com instrument
  • 如何使用 Twitter API 批准关注者对受保护帐户的请求?

    The 友谊 创造 https dev twitter com docs api 1 post friendships create似乎是最接近的选项 但他们的文档没有明确提及这种情况 有人能够做到这一点吗 我收到了 Twitter 员工的
  • 为什么使用 for 循环而不是 while 循环? [复制]

    这个问题在这里已经有答案了 可能的重复 使用 for 循环还是 while 循环进行迭代 https stackoverflow com questions 99164 iterate with for loop or while loop
  • 如何在innerText 或nodeValue 之间进行选择?

    当我需要更改 span 元素中的文本时 我应该使用哪一个以及有什么区别 var spnDetailDisplay document getElementById spnDetailDisplay spnDetailDisplay inner
  • 没有外键关系的内联管理

    是否可以手动指定要在内联中显示的相关对象集 其中不存在外键关系 Parent class Diary models Model day models DateField activities models TextField Child c
  • FFMPEG读取关键帧

    我正在尝试编写一个 C 程序 该程序将使用 ffmpeg 从视频文件中读取关键帧 到目前为止 我设法使用所有框架av read frame你按顺序阅读的地方 一帧一帧 但我在使用时遇到一些问题av seek frame这 如果我是正确的 应
  • 如何在不使用 eval 的情况下动态包含 Perl 模块?

    我需要动态包含 Perl 模块 但如果可能的话 由于工作编码标准 我希望远离 eval 这有效 module My module eval use module 但我需要一种方法来做到这一点 而不需要eval如果可能的话 所有谷歌搜索都会导
  • 客户端发送 SOAP 请求并接收响应

    尝试创建一个 C 客户端 将开发为 Windows 服务 将 SOAP 请求发送到 Web 服务 并获取结果 由此question https stackoverflow com questions 1862965 sending and
  • C++ 中使用运算符 [] 重载区分读和写

    我有一个包含预测数组的安全类 预测是一个类 它只包含一个双精度数 我想允许更改双精度值 但只允许正值 当尝试读取双精度值时 如果该值未初始化 在我的代码中等于 1 则会抛出异常 我也有双运算符像这样的东西 class Prediction
  • SWITCH javascript 总是执行默认情况的问题

    嗯 我有这个麻烦 我一直在处理 但我就是无法让它工作 我有这个功能 function getDirections dir var img switch dir case 0 img N png break case 1 img NE png
  • 正则表达式匹配完整字符串

    我正在尝试为 301 创建一个正则表达式来帮助我识别 url site com abc 并重定向到site com xyz 我尝试过正则表达式 abc 它工作正常 但问题甚至是像这样的网址site com 123 sdas abc 213被
  • Vue 组件中的 Laravel CSRF 字段

    我想问一下如何在我的 vue 组件中添加 csrf field 错误是 属性或方法 csrfToken 未在实例上定义 但在渲染期间引用 确保在数据选项中声明反应数据属性 这是代码
  • 获取数字的类似于 Excel 的列名称的算法

    我正在编写一个生成一些 Excel 文档的脚本 我需要将数字转换为其等效的列名称 例如 1 gt A 2 gt B 27 gt AA 28 gt AB 14558 gt UMX 我已经编写了一个算法来执行此操作 但我想知道是否有更简单或更快
  • 防止 this.state 与 setState 一起使用

    参考资料 https reactjs org docs react component html setstate states setState 并不总是立即更新组件 它可能会批量更新或推迟更新 这使得在调用 setState 后立即读取
  • Stackable Traits Pattern:方法的实现“需要‘抽象覆盖’修饰符”

    最近 我发现了可堆叠特征模式并遵循了所描述的示例here http www artima com scalazine articles stackable trait pattern html 一切正常 但有一种情况我无法理解 trait