From the link
http://www.scala-lang.org/old/node/117
It gives an example that a trait extends an abstract class.
Since abstract class has constructor, how could it happen? Does it mean abstract class and trait have the same position?
They are for sharing interfaces, fields and type between classes and both of them are not instantiatable. And a abstract class extends a trait and vice versa.
But since A class in scala can extend only one superclass,
abstract class A
abstract class B
trait AA extends A
class C extends AA // ok class C's super class is A
class C extends B with AA // NG trying to have 2 super class
like I mentioned at the beginning, they are non-instantiatable.
So You do not need to care the abstract class's constructor.
It will be called when a class which extends it is created and instantiated.
Related
I wrote some code for Logic Expressions in Scala and I was wondering if I could find a way to mix in a trait into an abstract class, so I don't have to extend it in every subclass. Here is what I've got:
abstract class LogicExpression
case class Literal(lit:String, not:Boolean) extends LogicExpression with Ordered[Literal]
case class Conjunction(lits:Seq[Literal]) extends LogicExpression with Ordered[Conjunction]
...
I want every case class to be only Comparable to another instance of itself (Literal with Literal, Conjunction only with Conjunction, etc) but I would like to extend the trait in the abstract class so I don't have to repeat it on every subclass. Is this possible?
I tried
abstract class LogicExpression extends Ordered[LogicFormula]
but that would also allow comparing Literal with Conjunction for example.
You need something like this:
sealed trait LogicExpression[T <: LogicExpression[T]] extends Ordered[T]
case class SomeExpression() extends LogicExpression[SomeExpression] {
override def compare(that: SomeExpression) = ???
}
While trying to learn Akka, I often find examples with a class hierarchy similar to this:
sealed trait Message
case class TextMessage(user: String, text: String) extends Message
case class StatusMessage(status: String) extends Message
However, in the Scala docs there's a following example:
abstract class Notification
case class Email(sourceEmail: String, title: String, body: String) extends Notification
case class SMS(sourceNumber: String, message: String) extends Notification
case class VoiceRecording(contactName: String, link: String) extends Notification
What's the difference in using a sealed trait vs. an abstract class (or sealed abstract class in this case) as a base class without constructor parameters for a class hierarchy? Are there some advantages in using one over the other?
Edit:
Specifically, if both, the trait and the abstract class are sealed, I can't extend them outside the file, right? In that case I couldn't inherit from them in Java either? If that's the case, being sealed would render most of the arguments found in the suggested duplicate useless since they refer to inheritance outside the file.
In this particular case there are no differences except that you can't extend multiple abstract classes but you can extend multiple traits.
You should check other answers (as mentioned in the comments) to see the actual differences between abstract classes and traits. If you are just going to use an abstract class or a trait to define the type hierarchy as in this case, then there are no differences.
E.g. you could to the following:
trait A
trait B
case class C(a: Int) extends A with B
but you can't do:
abstract class A
abstract class B
case class C(a: Int) extends A with B
I am confused. In my existing project, I am not able to find the difference between extends and with. Could you please help me?
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:
use of trait and (abstract) class is
here;
The resolution rule is the so-called
class linearization; there is a post about it.
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!
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.
If I have some class heirarchy defined like this
sealed trait A
case class B() extends A
case class C() extends A
// and so on ..
and in a different location I want to call some method dynamically passing above classes as type to that function
(eg: method[B](..){..} or method[C](..){..})
How can this be achieved at runtime?
I'm trying to understand the syntax for inheriting one class from another and it seems I must announce the constructor parameters of the parent when I create the child?
Why does this code not compile?
class Animal(name:String)
class Dog extends Animal //Here is where compiler error occurs
But this does
class Animal(name:String)
class Dog(name:String ) extends Animal(name)
Is their a reason I must explicitly say extends Animal(name) and not just extends Animal and the constructor be implied?
The Scala Language Specification doesn't (as far as I can see) discuss the reasons, but providing an implied constructor would be a special case, and would arguably be less clear.
Note that you can do things like:
class Animal(name:String)
class Dog extends Animal("Dog")
and
class Animal(name:String)
class Dog(n1: String, n2: String) extends Animal(n1 + n2)
So the current behaviour accommodates a variety of patterns in a uniform and explicit way.
Let's say you have two constructors for Animal:
class Animal(name:String) {
def this() = this("unnamed")
}
Which of them would you expect class Dog(name:String) extends Animal to use?