2012-09-05 42 views
3

,从而可以参照子类的类型更简单的方法,这里是一个有点做作的例子:试图找到从特质

trait MyTrait { 
    type T <: MyTrait 
    val listOfT:List[T] 
    def getFirst:T 
    //def getOne:T = if(listOfT.length > 0) { getFirst } else { this } 
} 

class MyClass extends MyTrait { 
    type T = MyClass 
    override val listOfT:List[T] = List[MyClass](this) 
    override def getFirst:T = listOfT.head 
} 

排序的问题有两个部分:

有一些其他的方式来在MyClass中的返回类型可以只是“MyClass”而不必指定“type T = MyClass”的情况下执行此操作吗?基本上我希望能够将这个特性添加到一个类中,而不必让子类显着改变它的实现,或者考虑类型系统......只返回它自己的成员,并且只要它具有该特性就可以接受在亚型上是协变的。这甚至有意义吗?

在MyTrait,如果取消注释,getOne方法将给出错误 “类型不匹配:” 实测值:MyTrait.this.type(与下面类型MyTrait)所需 :MyTrait.this.T

如果我要将返回类型更改为this.type,我会得到相反的发现/必需的类型不匹配。任何一个返回值实际上都具有相同的类型(并且实际上是同一个对象)。

处理这类情况的正确方法是什么?

回答

4

这是你想要的吗?

trait MyTrait[T <: MyTrait[T]] { self: T => 
    val listOfT: List[T] 
    def getFirst: T 
    def getOne: T = if (listOfT.length > 0) getFirst else self 
} 

class MyClass extends MyTrait[MyClass] { 
    override val listOfT: List[MyClass] = List[MyClass](this) 
    override def getFirst: MyClass = listOfT.head 
} 

它摆脱的type T = MyClass(允许你只是把MyClass在返回类型)和修复的getOne定义编译错误。

+0

嗯....是的工作,并解决了问题。有没有办法做到这一点,只是扩展MyTrait而不指定扩展MyTrait [MyClass]?在定义中重复子类的名字似乎有点奇怪,但这绝对比我如何处理它更简单/更简单。 – Brian

+0

MyClass扩展MyTrait [MyClass]实际上是一种相当常见的模式,在这种情况下,特征的方法需要知道实现类。例如,参见Seq [+ A]在Scala标准库中扩展了SeqLike [A,Seq [A]]。 – dhg

+0

hmm ....我只是注意到,现在如果在MyClass中我想调用getOne,我不能将结果赋给MyClass类型的变量,因为它是MyTrait [MyClass]? – Brian