为了账号安全,请及时绑定邮箱和手机立即绑定

自我类型和特质子类之间有什么区别?

自我类型和特质子类之间有什么区别?

自我类型和特质子类之间有什么区别?特征的自我类型A:trait Btrait A { this: B => }说"A不能混合到不扩展的具体类中。B".另一方面,以下方面:trait Btrait A extends B说“任何(具体或抽象的)类混合A也将混合在B中“.这两句话的意思不是一样吗?自我类型似乎只会造成简单编译时错误的可能性。我遗漏了什么?
查看完整描述

3 回答

?
叮当猫咪

TA贡献1776条经验 获得超12个赞

它主要用于依赖注入,比如蛋糕的图案。有一个伟大文章涵盖Scala中许多不同形式的依赖注入,包括Cake模式。如果你谷歌“蛋糕模式和Scala”,你会得到许多链接,包括演示文稿和视频。现在,这里有一个链接到另一个问题.

现在,关于自我类型和扩展特性之间的区别,这很简单。如果你说B extends A,然后B A..当你使用自我类型时,B 要求A..有两个特定的需求是用自我类型创建的:

  1. 如果

    B

    是扩展的,那么你.

    所需

    混入

    A.

  2. 当一个具体的类最终扩展/混合-在这些特征中,一些类/特征必须实现

    A.

考虑以下例子:

scala> trait User { def name: String }defined trait Userscala> trait Tweeter {
     |   user: User =>
     |   def tweet(msg: String) = println(s"$name: $msg")
     | }defined trait Tweeterscala> trait Wrong extends Tweeter {
     |   def noCanDo = name     | }<console>:9: error: illegal inheritance;
 self-type Wrong does not conform to Tweeter's selftype Tweeter with User
       trait Wrong extends Tweeter {
                           ^<console>:10: error: not found: value name         def noCanDo = name                       ^

如果Tweeter的子类User,就不会有错误。在上面的代码中,我们所需 a User什么时候都行Tweeter使用,但是User没有提供给Wrong所以我们发现了一个错误。现在,考虑到上面的代码仍然在范围内,请考虑:

scala> trait DummyUser extends User {
     |   override def name: String = "foo"
     | }defined trait DummyUserscala> trait Right extends Tweeter with User {
     |   val canDo = name     | }defined trait Right scala> trait RightAgain extends Tweeter with DummyUser {
     |   val canDo = name     | }defined trait RightAgain

带着Right,混合的要求User很满意。然而,上述第二项要求没有得到满足:执行的负担。User仍然存在于扩展的类/特性中Right.

带着RightAgain这两项要求都得到满足。一个User的实施User提供。

关于更实际的用例,请参阅这个答案开头的链接!但希望你现在明白了。


查看完整回答
反对 回复 2019-07-04
?
慕容708150

TA贡献1831条经验 获得超4个赞

Self类型允许您定义周期性依赖项。例如,您可以实现以下目标:

trait A { self: B => }trait B { self: A => }

继承使用extends不允许那样做。试着:

trait A extends Btrait B extends A
error:  illegal cyclic reference involving trait A

在Odersky书中,请参阅第33.5节(创建电子表格UI章节),其中提到:

在电子表格示例中,类模型继承了计算器,从而获得了对其计算方法的访问权。另一方面,类评估器将其Self类型定义为模型,如下所示:

package org.stairwaybook.scellstrait Evaluator { this: Model => ...

希望这能帮上忙。


查看完整回答
反对 回复 2019-07-04
?
汪汪一只猫

TA贡献1898条经验 获得超8个赞

另一个不同之处是,自类型可以指定非类型。例如

trait Foo{
   this: { def close:Unit} => 
   ...}

这里的Self类型是一种结构类型。其效果是说,在foo中混合的任何东西都必须实现一个no-arg“Close”方法返回单元。这允许安全的混合鸭类型.


查看完整回答
反对 回复 2019-07-04
  • 3 回答
  • 0 关注
  • 472 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信