猿问

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

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

特征的自我类型A:

trait Btrait A { this: B => }

"A不能混合到不扩展的具体类中。B".

另一方面,以下方面:

trait Btrait A extends B

“任何(具体或抽象的)类混合A也将混合在B中“.

这两句话的意思不是一样吗?自我类型似乎只会造成简单编译时错误的可能性。

我遗漏了什么?


繁星淼淼
浏览 473回答 3
3回答

叮当猫咪

它主要用于依赖注入,比如蛋糕的图案。有一个伟大文章涵盖Scala中许多不同形式的依赖注入,包括Cake模式。如果你谷歌“蛋糕模式和Scala”,你会得到许多链接,包括演示文稿和视频。现在,这里有一个链接到另一个问题.现在,关于自我类型和扩展特性之间的区别,这很简单。如果你说B extends A,然后B&nbsp;是阿A..当你使用自我类型时,B&nbsp;要求阿A..有两个特定的需求是用自我类型创建的:如果B是扩展的,那么你.所需混入A.当一个具体的类最终扩展/混合-在这些特征中,一些类/特征必须实现A.考虑以下例子:scala>&nbsp;trait&nbsp;User&nbsp;{&nbsp;def&nbsp;name:&nbsp;String&nbsp;}defined&nbsp;trait&nbsp;Userscala>&nbsp;trait&nbsp;Tweeter&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;user:&nbsp;User&nbsp;=> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;def&nbsp;tweet(msg:&nbsp;String)&nbsp;=&nbsp;println(s"$name:&nbsp;$msg") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;}defined&nbsp;trait&nbsp;Tweeterscala>&nbsp;trait&nbsp;Wrong&nbsp;extends&nbsp;Tweeter&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;def&nbsp;noCanDo&nbsp;=&nbsp;name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;}<console>:9:&nbsp;error:&nbsp;illegal&nbsp;inheritance; &nbsp;self-type&nbsp;Wrong&nbsp;does&nbsp;not&nbsp;conform&nbsp;to&nbsp;Tweeter's&nbsp;selftype&nbsp;Tweeter&nbsp;with&nbsp;User &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trait&nbsp;Wrong&nbsp;extends&nbsp;Tweeter&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;^<console>:10:&nbsp;error:&nbsp;not&nbsp;found:&nbsp;value&nbsp;name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;noCanDo&nbsp;=&nbsp;name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;^如果Tweeter的子类User,就不会有错误。在上面的代码中,我们所需&nbsp;a&nbsp;User什么时候都行Tweeter使用,但是User没有提供给Wrong所以我们发现了一个错误。现在,考虑到上面的代码仍然在范围内,请考虑:scala>&nbsp;trait&nbsp;DummyUser&nbsp;extends&nbsp;User&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;override&nbsp;def&nbsp;name:&nbsp;String&nbsp;=&nbsp;"foo" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;}defined&nbsp;trait&nbsp;DummyUserscala>&nbsp;trait&nbsp;Right&nbsp;extends&nbsp;Tweeter&nbsp;with&nbsp;User&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;val&nbsp;canDo&nbsp;=&nbsp;name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;}defined&nbsp;trait&nbsp;Right&nbsp;scala>&nbsp;trait&nbsp;RightAgain&nbsp;extends&nbsp;Tweeter&nbsp;with&nbsp;DummyUser&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;val&nbsp;canDo&nbsp;=&nbsp;name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;}defined&nbsp;trait&nbsp;RightAgain带着Right,混合的要求User很满意。然而,上述第二项要求没有得到满足:执行的负担。User仍然存在于扩展的类/特性中Right.带着RightAgain这两项要求都得到满足。一个User的实施User提供。关于更实际的用例,请参阅这个答案开头的链接!但希望你现在明白了。

慕容708150

Self类型允许您定义周期性依赖项。例如,您可以实现以下目标:trait&nbsp;A&nbsp;{&nbsp;self:&nbsp;B&nbsp;=>&nbsp;}trait&nbsp;B&nbsp;{&nbsp;self:&nbsp;A&nbsp;=>&nbsp;}继承使用extends不允许那样做。试着:trait&nbsp;A&nbsp;extends&nbsp;Btrait&nbsp;B&nbsp;extends&nbsp;A error:&nbsp;&nbsp;illegal&nbsp;cyclic&nbsp;reference&nbsp;involving&nbsp;trait&nbsp;A在Odersky书中,请参阅第33.5节(创建电子表格UI章节),其中提到:在电子表格示例中,类模型继承了计算器,从而获得了对其计算方法的访问权。另一方面,类评估器将其Self类型定义为模型,如下所示:package&nbsp;org.stairwaybook.scellstrait&nbsp;Evaluator&nbsp;{&nbsp;this:&nbsp;Model&nbsp;=>&nbsp;...希望这能帮上忙。

汪汪一只猫

另一个不同之处是,自类型可以指定非类型。例如trait&nbsp;Foo{ &nbsp;&nbsp;&nbsp;this:&nbsp;{&nbsp;def&nbsp;close:Unit}&nbsp;=>&nbsp; &nbsp;&nbsp;&nbsp;...}这里的Self类型是一种结构类型。其效果是说,在foo中混合的任何东西都必须实现一个no-arg“Close”方法返回单元。这允许安全的混合鸭类型.
随时随地看视频慕课网APP
我要回答