Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala Extending Parameterized Abstract Class

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?

like image 503
orrsella Avatar asked Sep 05 '12 21:09

orrsella


People also ask

Can you extend a case class Scala?

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.

Can an abstract class have parameters?

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.

What does <: mean in Scala?

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.

Can we create instance of abstract class in Scala?

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.


1 Answers

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.

like image 144
0__ Avatar answered Oct 01 '22 01:10

0__