自我有什么区别

自型的特质A

trait B
trait A { this: B => }

说“ A不能混入一个不扩展B的具体类”。

另一方面,以下是:

trait B
trait A extends B

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

这两个陈述不是同一件事吗? 自我类型似乎只会造成编译时错误的可能性。

我错过了什么?


它主要用于依赖注入,例如Cake模式。 在Scala中有很多不同形式的依赖注入,包括Cake模式。 如果你是谷歌的“蛋糕模式和斯卡拉”,你会得到很多链接,包括演示和视频。 现在,这里是另一个问题的链接。

现在,至于自我类型与扩展特质之间的区别是什么,那很简单。 如果你说B extends A ,那么BA 当你使用自我类型时, B需要一个A 有两种自我类型创建的具体要求:

  • 如果B延长,那么您需要混入A
  • 当一个具体类最终扩展/混合这些特征时,某些类/特征必须实现A
  • 考虑下面的例子:

    scala> trait User { def name: String }
    defined trait User
    
    scala> trait Tweeter {
         |   user: User =>
         |   def tweet(msg: String) = println(s"$name: $msg")
         | }
    defined trait Tweeter
    
    scala> 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
                           ^
    

    如果TweeterUser一个子类,则不会有错误。 在上面的代码中,每当使用Tweeter都要求User ,但是User没有提供Wrong ,所以我们得到了一个错误。 现在,上面的代码仍然在范围内,请考虑:

    scala> trait DummyUser extends User {
         |   override def name: String = "foo"
         | }
    defined trait DummyUser
    
    scala> 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提供。

    有关更多实际用例,请参阅此答案开始处的链接! 但是,希望现在你明白了。


    自我类型允许您定义循环依赖。 例如,你可以做到这一点:

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

    继承使用extends不允许。 尝试:

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

    在Odersky书中,请看第33.5节(创建电子表格用户界面章节),其中提到:

    在电子表格示例中,类Model继承自Evaluator,因此可以访问其评估方法。 换一种方式,类Evaluator将其自我类型定义为Model,如下所示:

    package org.stairwaybook.scells
    trait Evaluator { this: Model => ...
    

    希望这可以帮助。


    另一个区别是自我类型可以指定非类别类型。 例如

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

    这里的自我类型是结构类型。 其结果是,任何在Foo中混合的东西都必须实现一个无参数“close”方法的返回单元。 这为鸭子打字提供了安全的mixin。

    链接地址: http://www.djcxy.com/p/51019.html

    上一篇: What is the difference between self

    下一篇: Why can't a class extend traits with method of the same signature?