Scala 斯卡拉:试图理解特质;抽象覆盖';和堆叠
假设我有这样一个简单的抽象基类:Scala 斯卡拉:试图理解特质;抽象覆盖';和堆叠,scala,traits,Scala,Traits,假设我有这样一个简单的抽象基类: abstract class MyAbstractBaseClass { def hello : Unit } 然后我写了一个“堆叠”特征,如下所示: trait MyTrait extends MyAbstractBaseClass { abstract override def hello : Unit = { super.hello println("How ar
abstract class MyAbstractBaseClass {
def hello : Unit
}
然后我写了一个“堆叠”特征,如下所示:
trait MyTrait extends MyAbstractBaseClass {
abstract override def hello : Unit =
{
super.hello
println("How are you?");
}
}
那么为什么Scala不让我定义一个子类如下:
class MyClass extends MyAbstractBaseClass with MyTrait {
override def hello : Unit = println("Hello!")
}
error: overriding method hello in trait MyTrait of type => Unit;
method hello needs `abstract override' modifiers
如果我尝试使用“抽象覆盖”的建议:
class MyClass extends MyAbstractBaseClass with MyTrait {
abstract override def hello : Unit = println("Hello!")
}
error: `abstract override' modifier only allowed for members of traits
有人能帮我理解吗
另外,我知道以下方法确实有效:
class MyClass extends MyAbstractBaseClass {
override def hello : Unit = println("Hello!")
}
val x = new MyClass with MyTrait
x.hello
Hello!
How are you?
但我试图理解为什么前者没有
总而言之:为什么我不能提供抽象基类的实现——同时也利用trait的功能?诀窍在于,在线性化的流程中不能有一个“抽象”方法,即从
超级调用调用。
尝试此操作,您将看到它编译:
abstract class MyAbstractBaseClass {
def hello : Unit
}
class SubClass extends MyAbstractBaseClass {
def hello {
println("toto")
}
}
trait MyTrait extends MyAbstractBaseClass {
abstract override def hello : Unit =
{
super.hello
println("How are you?")
}
}
class MyClass extends SubClass with MyTrait { //note the CONCRETE SubClass here
override def hello : Unit = println("Hello!")
}
new MyClass().hello
您得到了错误,因为编译器以MyTrait
开始(在堆栈的顶部,因此是第一个被调用的),并且MyTrait
通过super
一个抽象方法调用。。。(属于MyAbstractBaseClass
)=>它崩溃了,因为您的super
调用不能立即以具体方法为目标
在我的代码片段中,您会注意到,
MyTrait
是一个具体的子类
类的“顶部”(在线性化过程中),这就构成了技巧 “abstract override”修饰符只允许traits的成员“+”错误:
abstract override”修饰符只允许traits的成员“=您不能重写类内抽象重写的方法感谢@dk14,我觉得我不能使用“abstract override”是有道理的。我不明白的是,为什么我不能提供抽象基类的实现——同时也利用trait的功能?如果在MyClass
定义中(在文章的第3栏中)删除override
关键字会怎么样。不能(从MyClass)重写标记为抽象重写的trait方法。最后一个块是有效的,因为带有traits的可堆叠堆栈是在有效编译MyClass
@Mik378之后生成的:然后我得到错误:覆盖trait MyTrait类型=>Unit中的方法hello;方法hello需要'override'修饰符你能在这里发布你更改的代码吗?谢谢你的详细回复。我确信我理解正确:在我的示例中,我以错误的顺序设置了堆栈(MyAbstractBaseClass No.在线性化时,hello
调用的顺序是:MyAbstractBaseClass
->MyClass
。因此,MyTrait
的hello
方法将调用MyAbstractBaseClass
的hello
方法……但它不是具体的方法!所以它不是comfile.在我的示例中,它将调用子类
,这是一个带有非抽象hello
方法的具体类。请注意,在第二个示例中,这是有效的:val x=new MyClass with MyTrait x.hello
,您将MyTrait
与一个名为MyClass
的具体类混合,正如前面所解释的,这是有效的。我已经知道了t尝试将MyAbstractBaseClass设置为一个具体的类(包括“hello”的实现)。如果我这样做,我的原始代码将编译,hello调用的顺序是MyClass、MyTrait,然后是MyAbstractBaseClass。而不是MyTrait、MyAbstractBaseClass,然后是MyClass。代码:class a{def hello=println(“a”)};trait B扩展了{abstract-override-def-hello={println(“B”);super.hello};类C用B{override-def-hello={println(“C”);super.hello};(新的C)扩展了A;