给出以下两个特征的示例,其中一个特征扩展另一个特征,每个特征没有实现 {/ 1}}:
def a
构造是否有用?有什么用例?
答案 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来引用我们正在混合的对象。这也禁止将该特性用作界面。