特质inheritance与自我types注释的区别
在斯卡拉,我已经看到了构造
trait T extends S
和
trait T { this: S =>
用来实现类似的事情(即S
中的抽象方法必须在创build实例之前被定义)。 他们之间有什么区别? 你为什么要用另一个呢?
我会使用自我types进行依赖pipe理:这个特性需要混合另一个特质。我会使用inheritance来优化另一个特性或接口。
举个例子:
trait FooService trait FooRemoting { this : FooService => } trait FooPersistence { this : FooService => } object Services extends FooService with FooRemoting with FooPersistence
现在,如果FooRemoting和FooPersistence都从FooServiceinheritance,而FooService有成员和方法,那么Services将如何?
而对于inheritance,我们会有这样的东西:
trait Iterator[T] { def hasNext : boolean def next : T } trait InfiniteIterator[T] extends Iterator[T] { def hasNext = true }
自我types注释允许您表示循环依赖关系。 例如:
trait A extends B trait B { self: A => }
这是简单的inheritance不可能的。
由于提出这个问题,我碰到这些post:
Spiros Tzavellas谈到使用特质作为公共接口和自我types作为帮助器,必须由实现类混合。
总而言之,如果我们想要在特征内部移动方法实现,那么我们就冒着用抽象方法来污染这些特征的接口,这些抽象方法支持具体方法的实现,而与特征的主要责任无关。 解决这个问题的方法是将这些抽象方法移动到其他特征中,并使用自我types注释和多重inheritance来组合特征。
例如:
trait PublicInterface { this: HelperTrait => // Uses helperMethod } trait HelperTrait { def helperMethod = // ... } class ImplementationClass extends PublicInterface with HelperTrait
Scala之旅讨论使用抽象types成员的自我types注释 – 大概是不可能extend
抽象types成员(?)
答案是“循环”。 但不仅如此。
自我types注释为我解决了inheritance的基本问题:你inheritance的东西不能使用你自己的东西。 随着自我types,一切都变得容易。
我的模式是以下,可以认为是一个退化的蛋糕:
trait A { self: X => def a = reuseme} trait B { self: X => def b = a } class X extends A with B { def reuseme=null }
您可以在多种行为中分解您的课程,这些行为可以在程序集中的任何位置调用,同时保持键入清晰。 不需要经常(和错误地)用蛋糕模式识别痛苦的间接方向。
在过去的十年中,一半(如果不是全部的)复杂的Java DI框架一直致力于这样做,当然不需要打字。 仍然在这个领域使用JAVA的人显然是在浪费时间:“SCALA ouakbar”。
虽然它不能回答你的问题,但是我试图理解自我types的注释,并且基本上在答案中迷失了方向,并且以某种方式结束了循环,通过你的问题的变化,重点在于使用自我types注释来表示依赖关系。
所以我在这里发表一个用例的描述,其中自我types的注释被很好的说明,就像一个types安全的“this”作为一个子types:
http://programming-scala.labs.oreilly.com/ch13.html#SelfTypeAnnotationsAndAbstractTypeMembers
希望对那些偶然遇到这个问题的人有所帮助(和我一样,在开始探索之前没有时间阅读Scala书籍:-))