CodeX
Published in

CodeX

The basics of abstract classes in Scala

This dramatic arrangement of chess pieces would never occur in an actual chess game. Photo by Felix Mittermeier on Unsplash

If you know abstract classes in Java, and you know a little bit about Scala syntax, you might think you already know how abstract classes work in Scala: pretty much the same as in Java, with a few minor differences.

And you’d be right. Scala abstract classes are a lot like Java abstract classes. The minor differences might trip you up occasionally, though. Or they might be pleasant surprises.

For this article, I’m going to assume that you indeed know about abstract classes in Java, so I won’t rehash the Java syntax, except to compare and contrast to Scala syntax.

And I also assume that you already know the reason to have abstract classes in the first place, so I won’t be going over that either.

For the example, I could use bank accounts: Account is an abstract class, CheckingAccount and SavingsAccount are “concrete” subclasses of Account.

That’s a good example, I think. But I’d prefer something a little less mundane, so, how about chess? The only downside of chess as an example is that not everyone reading this might know how to play. I’m not going to go too in-depth on chess, and I’ll try to explain everything that might not be obvious.

You’ve got an 8 by 8 checkerboard, and two sides with sixteen pieces each. The goal of the game is to trap the opponent’s king, while keeping your own king safe. All your other pieces are expendable, but it generally helps to have more pieces than your opponent.

Each chess piece has its own starting position and its own way of moving about the board. But surely the different pieces have enough in common that it might be worthwhile to create an abstract superclass for all of them.

package chessabstract class ChessPiece

Add a semicolon at the end of the first line and a pair of curly braces at the end of the last line and you’ve got something that a Java compiler should have no problem with.

Do note however that in a Java context, if ChessPiece is not explicitly marked public, it’s inaccessible outside of the chess package. Since most Java classes wind up being declared public anyway, Martin Odersky decided it made more sense for public to be the default for Scala classes and traits (interfaces).

In Scala just as with Java, an abstract class may have abstract “methods.”

package chessabstract class ChessPiece {  abstract def move(position: Position)}

The abstract modifier for move() is redundant and may be left out, just like the much-maligned semicolon can also be left out (though putting in a semicolon will give a warning).

package chessabstract class ChessPiece {  def move(position: Position)}

The subclasses of ChessPiece, such as Pawn and Rook (the one that looks like a tower) will have to define move(), unless they themselves are also abstract classes.

Whether abstract or not, a Java subclass can’t override the fields of a superclass. When a subclass has a field with the same name (but not necessarily the same type) as a field of the superclass, the superclass field is “hidden,” but still accessible. The subclass field does not actually override the superclass field.

Field hiding confuses a lot of Java beginners, and maybe even some professionals, too. When Martin Odersky designed Scala, he apparently decided it was one of those Java things he did not want in Scala.

So in Scala, subclass fields can override superclass fields, and the syntax is very similar to that for overriding superclass functions and procedures.

For this next example, I’m going to use the Boolean canJumpOver property of a chess piece. Most chess pieces can’t jump over other pieces of either player, but knights can (knights are the pieces that look like horses).

At the beginning of the game, either player may opt to start out by having one of their knights jump over pawns of their own side. Later on in the game, the ability to jump over pawns of either side can come in quite handy.

None of the other pieces can jump over other pieces. The queen, for example, is capable of moving from one side of the board to another in a single move. But at the beginning of the game, the queen is boxed in by pawns in front and a bishop and the king at the sides.

Therefore it makes sense for ChessPiece to declare canJumpOver as false.

package chessabstract class ChessPiece {
val canJumpOver: Boolean = false
def move(position: Position)}

And then Knight can override that, just like it overrides move().

package chessclass Knight extends ChessPiece {
override val canJumpOver: Boolean = true
override def move(position: Position): Unit = {
// TODO: Figure out what this needs to do
}
}

Alternatively, we can do this:

package chessabstract class ChessPiece {
val canJumpOver: Boolean
def move(position: Position)}

But then we’d have have to write “override val canJumpOver: Boolean = true” in Queen, Bishop, Knight, etc. That wouldn’t be very “DRY” (meaning “don’t repeat yourself”).

Unless those classes were also abstract classes. Though it really doesn’t make much sense to kick this particular can down the road.

If we were doing this with Java, we should probably make this a Boolean call rather than a Boolean field, so as to avoid the problems that come with field hiding, like this for example:

package chess;public abstract class ChessPiece {

public boolean canJumpOver() {
return true;
}
abstract void move(Position position);}

Maybe the Java and Scala versions of ChessPiece compiles to the same thing, or almost the same thing. But hopefully the Scala version is much more intuitive than the Java version.

That’s it, those are the basics of abstract classes in Scala. Not much to it, it’s a simple concept that builds on the Java concept.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store