Inheritance 是否有一个“问题”;“自我”;是否在表示当前类型的scala中键入?
我正在学习Scala,但有一件事我找不到:Inheritance 是否有一个“问题”;“自我”;是否在表示当前类型的scala中键入?,inheritance,scala,Inheritance,Scala,我正在学习Scala,但有一件事我找不到: trait Container[E <: Element] { def elements: Seq[E] def add(elem: E): Unit } trait Element { // the type parameter would be redundant ... def save() = container.add(this) // ... and this would be possible, too, ...
trait Container[E <: Element] {
def elements: Seq[E]
def add(elem: E): Unit
}
trait Element { // the type parameter would be redundant ...
def save() = container.add(this) // ... and this would be possible, too, ...
def container: Container[this] // ... if only we could do this
}
不久前,我在Lisaac中编程非常自如,在Lisaac中我可以编写一个类PERSON
,其中包含一个插槽list:ARRAY[SELF]
,这相当于拥有list:ARRAY[PERSON]
,因为SELF
是该插槽所在对象的类型
但是通过使用SELF
,如果我写了一个从PERSON
继承的第二个类STUDENT
,那么STUDENT
将继承STUDENT
的槽位更改SELF
,因此STUDENT
将有一个STUDENT
的列表,而不是PERSON
这可以在Scala中实现吗?关于那件事我什么也找不到
谢谢 Scala中的
这个
关键字或多或少是等效的
在开发可扩展软件时,有时可以方便地明确声明值的类型this
:
在Scala中显式键入自引用我不确定这是否真的对您有用,但我能想到的最贴切的事情是
这个。键入
。例如:
scala> class A { val l: List[this.type] = Nil }
defined class A
scala> new A().l
res3: List[A] = List()
scala> class B extends A
defined class B
scala> new B().l
res4: List[B] = List()
单例类型和ETSR不能解决这个问题。我自己也在Scala中寻找同样的特性,但显然它缺少所谓的自类型注释 在某些情况下,此类自类型注释可能非常有用。考虑一个例子(改编自): 一切正常,一切正常。唯一值得关注的是,库使用者应该使用自绑定类型参数(代码中的#1)。但这还不是全部。现在假设您考虑了某种类型的ActiveRecord模式,并且希望将方法
save
添加到元素
,该方法只委托给它的容器的add
方法。令人惊讶的是,这并不那么容易:
trait Element[E <: Element[E]] {
def container: Container[E]
def save() = container.add(this) // won't compile
}
found : Element[E]
required: E
如果编译器可以在方括号内使用this
(或者另一个关键字)作为实际实现的类型(即与obj.getClass
的结果相同的类型),那么问题就会消失
有人会考虑把这些东西列入斯卡拉的愿望清单吗?不幸的是,我不知道实现这样的逻辑有多困难,因为臭名昭著的JVM擦除可能存在问题
p.p.S.或者可能还有另一种我不知道的Scala方式?这有一个习惯用法,它在集合框架中被广泛使用(在所有类似*的类中,例如TraversableLike)。 您需要将自类型添加为类型参数(如C++中可能的)与超类:
trait Person[+Self] {
this: Self => //Declare that any concrete subclass must implement Self; therefore, this can be used with type Self.
//val list: Array[Self] //Not sure that this will work so easily, for the same reason new T[] does not work in Java.
val list = Seq[Self]() //No problem here; Array is really special.
}
定义此类后,我们可以尝试在解释器中定义子类:
scala> class Student extends Person[Student]
defined class Student
scala> (new Student).list
res0: Seq[Student] = List() //Note the result type
scala> class Student2 extends Person[Student] //Note the mistake
<console>:9: error: illegal inheritance;
self-type Student2 does not conform to Person[Student]'s selftype Person[Student] with Student
class Student2 extends Person[Student]
由于Self
前面的+
使其成为一个协变类型参数(我不解释它是什么),但这至少是可能的:
scala> class SpecStudentCorrect extends Student with Person[SpecStudentCorrect]
scala> (new SpecStudentCorrect).list
(new SpecStudentCorrect).list
res1: Seq[SpecStudentCorrect] = List()
我不认为“这个.类型”是这里所需要的。“this.type”是单例类型;它只是“this”实例的类型。尽管您可以尝试,但“List[this.type]”可以包含的有效元素是“this”。是的,您是对的。我试图准确地记住它是如何工作的。在trait元素中需要一个self-type注释:
trait元素[E…}
一旦你有了它,你就可以省去类型绑定。this
关键字并不表示类型。>Scala中的this关键字或多或少是等价的。你指的是什么?如果它不等价于Lisaac的SELF(这是一种类型),那么你的意思是什么?OP要求一种表示类型的方法,因为他想写一些类似“Array[Self]”的东西。有一种常用的模式可以实现这一点,即使它有局限性(参见我的答案)。当然,我提供的链接澄清了问题。我看了一下;再看一遍,我意识到它显示了另一种解决方案,Self
被声明为一个抽象成员,而不是一个参数。你确定这个超过两年的问题没有被接受的答案充分涵盖吗?如果你阅读了对answ的评论呃,你会同意我的。而且,你为什么认为我没有检查,甚至没有阅读接受的答案?现在,你提供的链接确实提供了一个比接受的答案更好的答案,但我确实发现你的答案的文本令人困惑。然而,我给出的解决方案是最常用的,也是因为它比o该链接中描述的ne:当type
是同一类的抽象类型成员时,不能添加像this:type=>
这样的自类型注释,但只有当它在外部类中时才可以。例如,trait Person{this:self=>type self}或trait FooBase{type Bar};trait FooDer扩展FooBase{this:Bar=>}
可以工作,因为找不到Bar
。这在嵌套多个需要这些自身类型的类型时特别有用。
scala> class Student extends Person[Student]
defined class Student
scala> (new Student).list
res0: Seq[Student] = List() //Note the result type
scala> class Student2 extends Person[Student] //Note the mistake
<console>:9: error: illegal inheritance;
self-type Student2 does not conform to Person[Student]'s selftype Person[Student] with Student
class Student2 extends Person[Student]
scala> class SpecStudent extends Student
defined class SpecStudent
scala> class SpecStudentCorrect extends Student with Person[SpecStudentCorrect]
scala> (new SpecStudentCorrect).list
(new SpecStudentCorrect).list
res1: Seq[SpecStudentCorrect] = List()