Scala - extends与with的区别

54

我很困惑。在我的现有项目中,我无法找到extendswith之间的区别。请问您能帮我吗?


extends 用于对象或类,而 with 用于接口或特质。 - HuntsMan
6
马丁·奥德斯基为此写了一个不错的答案,链接在这里:http://www.scala-lang.org/old/node/10145.html。 - raam86
3个回答

44

如果你有多个要继承的classtrait,第一个是extends,后面的>=0个class/trait需要使用with

但请记住,你只能继承<=1个(抽象)类,这意味着如果你需要继承一个父类(Parent),它应该始终出现在形式的最前面... extends Parent ...,并且不能再继承其他类到派生类。

trait T1
trait T2
class P1
class P2

class C1 extends T1
class C2 extends T1 with T2
class C3 extends T2 with T1
class C4 extends P1 with T1
/// class C5 extends T1 with P1 // invalid
/// class C6 extends P1 with P2 // invalid

with 实际上绑定到被 extend 的类/特质,例如,class C7 extends P1 with T1 with T2 读作 class C7 extends (P1 with T1 with T2)

需要注意的是,这只是从语法的角度来看,语义上的区别可以从以下内容中参考:

  1. 使用 trait 和 (abstract) class 的优势在于这里
  2. 解析规则是所谓的类线性化;关于它有一篇文章

26

在Scala中,您可以继承自具体的或抽象的classtrait。与Java中您可以扩展一个类,但实现任意数量的接口类似,您只能从一个class继承,但是可以从任意数量的trait继承。

如果您正在扩展一个class,该class应紧跟在extends关键字之后。您要扩展的任何trait应跟在其后,用with关键字隔开。

如果您不扩展任何class,则可以将第一个trait放在extends关键字之后,并在此之后继续添加。

与Java一样,每个类都是Object的子类,无论您是否显式声明,每个(用户定义的)Scala类都extends AnyRef with ScalaObject,无论您是否显式包含它。

因此,以下声明集是等效的:

class MyClass { ... }
class MyClass extends AnyRef with ScalaObject { ... }

class MyClass extends MySuperClass { ... }
class MyClass extends MySuperClass with ScalaObject { ... }

class MyClass extends MyTrait1 with MyTrait2 { ... }
class MyClass extends AnyRef with MyTrait1 with MyTrait2 { ... }

class MyClass extends MySuperClass with MyTrait1 with MyTrait2 { ... }
如果你改变MySuperClassMyTrait1MyTrait2的顺序,那么最后一个例子就不一样了。特别地,你不能把trait放在类前面,并且如果它们都对同一个方法有实现,那么组合trait的顺序很重要(在这种情况下,以最后一个为准)。

请记住,只有Scala中的class可以有参数,因此您只能将参数附加到extends关键字之后的类型,而不能将其附加到with之后列出的任何类型。

希望这可以帮到你!


1
有没有关于为什么第一个 trait 必须在 "extends" 关键字之后而不是 "with" 关键字的文档?在你的例子中,它是这样的:class MyClass extends MyTrait1 with MyTrait2 { ... } - Alex
1
那只是语法问题,没有特别的原因,只是为了让英语听起来合理而已(“extends _ with _”是一个合理的描述性短语)。 - Todd O'Bryan

12

你从中继承的第一件事可以是特征或类,使用extends关键字。

trait SomeTrait
class SomeClass

class ThisIsValid extends SomeTrait
class ThisAsWell extends SomeClass

您可以使用with关键字定义进一步继承的特征(仅限特征)。

class AlsoThisWorks extends SomeClass with SomeTrait

如果一个特征从一个类中继承,你不能像上面的例子那样使用它。

以上就是关于extendswith关键字的全部内容。如果你想学习更多关于特征的知识,官方文档会深入介绍这个主题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接