Scala - extends vs with

前端 未结 3 1174
渐次进展
渐次进展 2021-01-31 16:02

I am confused. In my existing project, I am not able to find the difference between extends and with. Could you please help me?

相关标签:
3条回答
  • 2021-01-31 16:10

    The first thing you inherit from can either be a trait or a class, using the extends keyword.

    trait SomeTrait
    class SomeClass
    
    class ThisIsValid extends SomeTrait
    class ThisAsWell extends SomeClass
    

    You can define further inherited traits (and only traits) using the with keyword.

    class AlsoThisWorks extends SomeClass with SomeTrait
    

    If a trait inherits from a class you cannot use it like in the above example.

    That's it regarding the extends and with keywords. If you want to learn more about classes and traits the official documentation goes in depth on the topic.

    0 讨论(0)
  • 2021-01-31 16:27

    If you have multiple classes or traits to inherit, the first one is always extends, and the following >=0 class/trait to be withs.

    But remember that you can only inherit <=1 (abstract) class, which means if you need to inherit a parent class (Parent), it should always comes at first of the form ... extends Parent ..., and no more classes can be inherited to the derived class.

    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 is in fact bound to the class/trait that is extended, e.g., class C7 extends P1 with T1 with T2 reads class C7 extends (P1 with T1 with T2).

    Note that this is only from the viewpoint of syntax, the semantic differences can be referred from the followings:

    1. use of trait and (abstract) class is here;
    2. The resolution rule is the so-called class linearization; there is a post about it.
    0 讨论(0)
  • 2021-01-31 16:30

    In Scala, you can inherit from classes (concrete or abstract) and traits. In a similar way to how you can extend only one class, but implement as many interfaces as you'd like in Java, you're only allowed to inherit from one class, but as many traits as you'd like.

    If you are extending a class, that class should immediately follow the extends keyword. Any traits you are extending from should follow, separated by with keywords.

    If you are not extending a class, you can put your first trait right after the extends keyword and continue after that.

    Just as in Java, every class is a subclass of Object whether you explicitly declare it or not, every (user-defined) class in Scala extends AnyRef with ScalaObject whether or not you include that explicitly.

    The following sets of declarations are therefore equivalent:

    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 { ... }
    

    The last example is not the same if you change the order of MySuperClass, MyTrait1, and MyTrait2. In particular, you cannot put a trait in front of a class and the order in which you stack traits is important if they both have implementations for the same methods. (In that case, the last one "wins".)

    Remember also that only classes in Scala can have parameters, so you'll only ever be able to attach parameters to the type after the extends keyword, never to any of the types listed after with.

    Hope that helps!

    0 讨论(0)
提交回复
热议问题