Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 斯卡拉:试图理解特质;抽象覆盖';和堆叠_Scala_Traits - Fatal编程技术网

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;