在哪里"抽象覆盖"没有实现的子程序是否有用,如果有的话?

时间:2015-03-01 18:49:26

标签: scala traits

给出以下两个特征的示例,其中一个特征扩展另一个特征,每个特征没有实现 {/ 1}}:

def a

构造是否有用?有什么用例?

3 个答案:

答案 0 :(得分:3)

我认为答案基本上与评论中链接的答案相同。在Scala中,不需要方法的abstract关键字,因为编译器可以根据它是否具有实现来确定它是否是抽象的。所以这里的用法是多余的。

实现抽象方法的方法也不需要override关键字(或者我想在这种情况下根本不做任何事情)。实际上,B相当于:

trait B extends A { def a: String }

或者只是(因为B将被假定为抽象):

trait B extends A

与链接的答案类似,我可以想象一次使用override可能对可读性有用的场景。如果我在a中的B的返回类型比A更具体,我可以使用override作为我正在以某种方式修改行为的提示:

trait A {
    def a: Any
}

trait B extends A {
   override def a: String
}

在这种情况下,我暗示a中的B可能与A的继承签名略有不同。当然,这只有在读者知道并以一致的方式使用时才有用。但是如果没有override,我仍然可以做同样的事情。

答案 1 :(得分:3)

简短回答:abstract override在这种情况下没用。它基本上就像给出一个不需要的类型注释。

abstract override的增值使用用于装饰将在稍后混合的实现,有时称为"可堆叠特征模式"。请参阅Why is "abstract override" required not "override" alone in subtrait?

答案 2 :(得分:2)

抽象覆盖表示您希望覆盖“抽象”方法。其他人解决了为什么它在这里没用,所以我将专注于一个例子。抽象覆盖最适用于mixins。一个简单的例子是Pollable trait:

trait Pollable{def poll:Double}

让我们说我们想要加权这个pollable。这个特性将成为我们特质的混合体。我们的加权可轮询将有一个权重字段,它将乘以一个轮询以获得结果。例如:

class OnePollable extends Pollable{
    def poll:Double=1
}
val myWeightedOne=new OnePollable with WeightedPollable;

让我们尝试写下这个特性:

//Does not compile
trait WeightedPollable extends Pollable{
    var weight=1
    def poll:Double=super.poll*weight
}

如果你看,你会清楚地看到为什么这不起作用。我们的特性试图调用一个未实现的超类型方法!一种解决方案是在超级特征Pollable:

中添加默认值
//Don't do this!
trait Pollable{def poll:Double=1}

这种方法在这里工作,但在很多现实世界的应用程序中都很笨拙。更好的方法是:

trait WeightedPollable extends Pollable{
    var weight=1
    abstract override def poll:Double=super.poll*weight
}

这是我们的朋友abstract override修饰符!这告诉编译器我们覆盖 抽象方法,但我们想使用super来引用我们正在混合的对象。这也禁止将该特性用作界面。