I'm fairly new to Scala, and am writing an API library and trying to use only vals and immutable objects (where possible). I'm trying to decide on the right way to model the objects. Suppose there are several "Post" objects, which all share some common fields, and each adds its own specific fields:
abstract class Post(val id: Int, val name: String, ...)
case class TextPost(val id: Int, val name: String, ..., val text: String) extends Post(id, name, ...)
case class PhotoPost(val id: Int, val name: String, ..., val url: String) extends Post(id, name, ...)
This method adds a lot of repetitive declarations and boiler-plate code, especially when dealing with many Post subclasses and shared fields declare in the abstract class. The way I see it, this is caused by the use of vals which can only be initialized by the constructor. Is there a better way to create the relationships detailed here, or must I suffer this for wanting to use only immutable objects?
To extend a class in Scala we use extends keyword. there are two restrictions to extend a class in Scala : To override method in scala override keyword is required.
Yes, we can provide parameters to abstract method but it is must to provide same type of parameters to the implemented methods we wrote in the derived classes.
It means an abstract type member is defined (inside some context, e.g. a trait or class), so that concrete implementations of that context must define that type.
Like Java, in Scala, we are not allowed to create the instance of the abstract class. If we try to create objects of the abstract class, then the compiler will give an error as shown in the below program. In Scala, an abstract class can also contain fields.
First of all, the val
modifiers in the case-class constructors are redundant, the Scala compiler will give them to you already "for free" (it's one of the features of case-classes). If you actually tried to compile that, you will see that an error occurs because of undeclared overriding:
abstract class Post(val id: Int, val name: String )
case class TextPost(id: Int, name: String) extends Post(id, name )
case class PhotoPost(id: Int, name: String) extends Post(id, name )
<console>:10: error: overriding value id in class Post of type Int;
value id needs `override' modifier
case class PhotoPost(id: Int, name: String) extends Post(id, name )
^
I personally recommend to use abstract classes with constructor arguments as little as possible. Scala has traits which do a better job here. Instead of constructor arguments, you declare (abstractly) the fields; then the case classes kick in and due to them making their arguments automatically vals
, you are done:
trait Post { def id: Int; def name: String }
case class TextPost(id: Int, name: String, text: String) extends Post
case class PhotoPost(id: Int, name: String, url: String) extends Post
Furthermore, if you add sealed
to the trait Post
, you can safely use the subtypes of Post
in pattern matching without accidentally missing cases.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With