Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Scala Programming Projects
Scala Programming Projects

Scala Programming Projects: Build real-world projects using popular Scala frameworks such as Play, Akka, and Spark

eBook
€22.99 €32.99
Paperback
€41.99
Subscription
Free Trial
Renews at €18.99p/m

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Table of content icon View table of contents Preview book icon Preview Book

Scala Programming Projects

Writing Your First Program

In 2001, Martin Odersky started to design the Scala language – it took him three years to release the first public version. The name comes from Scalable language. This was chosen because Scala is designed to grow with the requirements of its users – you can use Scala for small scripts or for large enterprise applications.

Scala has been constantly evolving ever since, with a growing popularity. As a general purpose language, it is used in many different industries such as finance, telecoms, retail, and media. It is particularly compelling in distributed scalable systems and big data processing. Many leading open source software projects have been developed in Scala, such as Apache Spark, Apache Kafka, Finagle (by Twitter), and Akka. A large number of companies use Scala in production, such as Morgan Stanley, Barclays, Twitter, LinkedIn, The Guardian, and Sony.

Scala is not an extension of Java but is fully interoperable with it. You can call Java code from Scala, and you can call Scala code from Java. There is also a compiler to JavaScript, which we will explore later on in this book. You can, therefore, run Scala code in your browser.

Scala is a blend of object-oriented and functional programming paradigms, and it is statically typed. As such, it can serve as a bridge for people from an object-oriented or imperative background to move gradually to functional programming.

In this chapter, we will cover the following topics:

  • Setting up your environment
  • Using the basic features
  • Running the Scala Console
  • Using the Scala Console and Worksheet
  • Creating my first project

Setting up your environment

First things first, we need to set up our work environment. In this section, we will get all the tools and libraries, and then install and configure them on your computer.

Scala programs are compiled to Java bytecode, which is a kind of assembly language that can be executed using a Java Virtual Machine (JVM). You will, therefore, need to have a Java compiler and a JVM installed on your computer. The Java Development Kit (JDK) provides both components, alongside other tools.

You could develop in Scala using a simple text editor and compile your programs using the Scala Simple Build Tool (SBT). However, this would not be a pleasant nor productive experience. The majority of professional Scala developers use an Integrated Development Environment (IDE), which provides many helpful features such as syntax highlighting, autocompletion, code navigation, integration with SBT, and many more. The most widely used IDE for Scala is IntelliJ Idea from JetBrains, and this is the one we are going to install and use in this book. The other options are Scala IDE for Eclipse and ENSIME. ENSIME is an open source project that brings IDE-like features to popular text editors such as Emacs, Vim, Atom, Sublime, and VSC.

Installing the Java SDK

We are going to install the Oracle JDK, which includes a JVM and a Java compiler. On many Linux distributions, the open source OpenJDK is preinstalled. OpenJDK is fully compatible with the Oracle JDK, so if you already have it you do not need to install anything else to follow this book.

You might already have a Java SDK installed on your computer. We are going to check if this is the case. If you are using Windows, open a DOS Command Prompt. If you are using macOS or Linux, open a Terminal. After the prompt, type the following:

javac -version

If you have a JDK installed, the version of the installed compiler will be printed:

javac 1.8.0_112

If the version installed is greater than or equal to 1.8.0_112, you can skip the JDK installation. The version of Scala that we are going to use is compatible with JDK version 1.8 or 1.9.

If not, open the following URL, download the SDK for your platform, and follow the installation instructions given: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html.

Installing IntelliJ IDEA

Go to https://www.jetbrains.com/idea/download. Download the community edition for your platform. The ultimate edition offers more features, but we will not use them in this book.

The following are the steps to install IntelliJ IDEA:

  1. Run IntelliJ Idea.
  2. Select the Do not import settings option:

  1. Choose a UI theme. I personally prefer Dracula, since a dark background saves battery on a laptop and is more gentle on the eyes:

  1.  Create a desktop entry by checking the options given:

  1. In the Create Launcher Script dialog window, check the create a script... checkbox. It will let you open files in IntelliJ from the command line:

  1. Customize the plugins. For each component, click on Customize... or Disable All. We will not need most of the plugins. You can only select the following:
  • Build Tools: Disable All.
  • Version Controls: Only keep Git and GitHub.
  • Test Tools: Disable All.
  • Swing: Disable.
  • Android: Disable.
  • Other Tools: Disable All and keep Bytecode viewer, Terminal, and YAML.
  • Plugin Development: Disable.

You can see the aforementioned plugins in the following screenshot:

  1. Install the featured plugins—some additional plugins are proposed for you to install, such as the Scala plugin and a tool to learn the essential features of IntelliJ.
  1. Click on the Install button for Scala and for the IDE Features Trainer, as shown in the following screenshot, and then proceed by clicking on Start using IntelliJ IDEA:

If you are already a Vim aficionado, you can install IdeaVim. Otherwise, I would recommend that you avoid it. I personally use it daily, but it took me some time to get used to it.
  1. Click on Create New Project | Scalasbt:

  1. Fill in the following details, as shown in the following screenshot:
  • Name: scala_fundamentals.
  • JDK: Click on New and then select the installation directory of the Oracle JDK.
  • sbt: Choose the version 1.0.4, check Sources.
  • Scala: Choose the latest version 2.12.x, for instance 2.12.4 (IntelliJ lists all the possible versions and will download the one you choose), and check Sources.
  • Click on Finish.

It is going to take some time depending on your internet connection's speed:

  1. You should see the following project structure:

Using the basic features

In this section, and in the rest of this book, we will highlight some key shortcuts in italics. I strongly encourage you to use and remember these shortcuts. They save a tremendous amount of time and will keep you focused on the task at hand. If you cannot remember a shortcut, you can use the mother of all shortcuts, Ctrl + Shift + A (Windows/Linux) or cmd + shift + A (macOS), and type the name of the action you are looking for.

If you are using IntelliJ for the first time, I find it useful to display all tool buttons. Go to the View menu, and check Toolbar and Tool buttons.

SBT synchronization

Now, let's have a look at our build configuration. SBT (short for Simple Build Tool) is the de facto build tool in the Scala community. Double-click on build.sbt:

name := 'scala_fundamentals"

version := "0.1"

scalaVersion := "2.12.4"

This file describes how SBT will compile, test, and deploy our project. For now, it is fairly simple.

One important thing to keep in mind is that IntelliJ manages its own set of files to define a project structure. They are located in the .idea directory of your project.
Whenever you change build.sbt, IntelliJ has to interpret the changes and translate them.

For instance, If I change the Scala version to 2.12.3 and save (Ctrl + S or cmd + S), IntelliJ will propose to synchronize the changes or enable autoimport:

On a small project, it is ok to use autoimport, but on a large one, it can be a bit annoying. The synchronization can take time and it might kick off too often.

When you program in Scala using IntelliJ, you therefore have two ways of compiling your project:

  • SBT, in which case you would only use IntelliJ as an advanced text editor
  • IntelliJ

You could, in theory, mix and match: start building with SBT and continue with IntelliJ or the other way around. However, I strongly discourage you to do so, as you may get some unexpected compilation errors. When you want to switch to one tool or the other, it is best to clean all compiled files first.

We will further expand on SBT later in this book, but for now, we are only going to use IntelliJ's own build.

Build

The project has been created and ready to be built. The build process does the following:

  • Compiles the source files present at the source path and the test path
  • Copies any resource files needed in the output path
  • Reports any errors/warnings in the Message tool window

There are two ways to build the project:

  • If you want to build your project incrementally, go to Build | Build Project (Ctrl + F9 or cmd + F9)
  • If you want to delete all files and rebuild everything, go to Build | Rebuild All

As we do not have a source yet, the build is fast and no errors should appear in the Message tool window.

Running the Scala Console

In IntelliJ, you need to have a run configuration whenever you want to run something: a program, a unit test, an external tool. A run configuration sets up the classpath, arguments, and environment variables that you need to run your executable.

We need to create a run configuration the first time we want to run the Scala console:

  1. Go to Run | Edit Configurations. Click on the green + button, and select Scala Console. You should see the following screen:

  1. Make the following changes and click OK:
  • Name: Scala Console.
  • Check Single instance only box – we rarely need to have two consoles running at the same time.
  • In, Before launch, click on Build and then click the Remove button. This way, you will always be able to quickly run a console, even if your code does not compile.
  • Following that, click on OK.
  1.  On the top toolbar, you should see that IntelliJ created a new Scala Console run configuration:

 

  1. Click on the green arrow to run the console. You should see the following at the bottom of the screen, in the Run window. We can now type our first Scala expression after the Scala prompt:

Using the Scala Console and Worksheet

By now, all the necessary tools and libraries should be installed. Let's start to play with the basics of Scala by experimenting in different environments. The simplest way to try Scala is to use the Scala Console. Subsequently, we will introduce the Scala Worksheet, which allows you to keep all the instructions that are entered in a file.

Using the Scala Console

The Scala console, also called Scala REPL (short for Read-Eval-Print-Loop), allows you to execute bits of code without having to compile them beforehand. It is a very convenient tool to experiment with the language or when you want to explore the capabilities of a library.

In the console, type 1+1 after the scala> prompt and hit Ctrl + Enter or cmd + Enter:

scala> 1+1

The console displays the result of the evaluation, like so:

res0: Int = 2

What happened here? The REPL compiled, evaluated the expression 1+1, and automatically assigned it to a variable named res0. This variable is of type Int, and its value is 2.

Declaring variables

In Scala, a variable can be declared using val or var. A val is immutable, which means you can never change its value. A var is mutable. It is not mandatory to declare the type of the variable. If you do not declare it, Scala will infer it for you.

Let's define some immutable variables:

In all the following code examples, you only need to type the code that is after the Scala Command Prompt, and hit Ctrl + Enter or cmd + return to evaluate. We show the result of the evaluation underneath the prompt, as it would appear on your screen.
scala> val x = 1 + 1
x: Int = 2

scala> val y: Int = 1 + 1
y: Int = 2

In both cases, the type of the variable is Int. The type of x was inferred by the compiler to be Int. The type of y was explicitly specified with : Int after the name of the variable.

We can define a mutable variable and modify it as follows:

scala> var x = 1
x: Int = 1

scala> x = 2
x: Int = 2

It is a good practice to use val in most situations. Whenever I see a val declared, I know that its content will never change subsequently. It helps to reason about a program, especially when multiple threads are running. You can share an immutable variable across multiple threads without fearing that one thread might see a different value at some point. Whenever you see a Scala program using var, it should make you raise an eyebrow: the programmer should have a good reason to use a mutable variable, and it should be documented.

If we attempt to modify a val, the compiler will raise an error message:

scala> val y = 1
y: Int = 1

scala> y = 2
<console>:12: error: reassignment to val
y = 2
^

This is a good thing: the compiler helps us make sure that no piece of code can ever modify a val.

Types

We saw in the previous examples that Scala expressions have a type. For instance, the value 1 is of type Int, and the expression 1+1 is also of type Int. A type is a classification of data and provides a finite or infinite set of values. An expression of a given type can take any of its provided values.

Here are a few examples of types available in Scala:

  • Int provides a finite set of values, which are all the integers between -231 and 231-1.
  • Boolean provides a finite set of two values: true and false.
  • Double provides a finite set of values: all the 64 bits and IEEE-754 floating point numbers.
  • String provides an infinite set of values: all the sequence of characters are of an arbitrary length. For instance, "Hello World" or "Scala is great !".

A type determines the operations that can be performed on the data. For instance, you can use the + operator with two expressions of type Int or String, but not with expressions of type Boolean:

scala> val str = "Hello" + "World"
str: String = HelloWorld

scala> val i = 1 + 1
i: Int = 2

scala> val b = true + false
<console>:11: error: type mismatch;
found : Boolean(false)

When we attempt to use an operation on a type that does not support it, the Scala compiler complains of a type mismatch error.

An important feature of Scala is that it is a statically typed language. This means that the type of a variable or expression is known at compile time. The compiler will also check that you do not call an operation or function that is not legal for this type. This helps tremendously to reduce the number of bugs that can occur at runtime (when running a program).

As we saw earlier, the type of an expression can be specified explicitly with : followed by the name of the type, or in many cases, it can be automatically inferred by the compiler.

If you are not used to working with statically typed languages, you might get frustrated to have to fight with the compiler to make it accept your code, but you will gradually get more accustomed to the kind of errors thrown at you and how to resolve them. You will soon find that the compiler is not an enemy that prevents you from running your code; it is acting more like a good friend that shows you what logical errors you have made and gives you some indication on how to resolve them.

People coming from dynamically typed languages such as Python, or people coming from not-as-strongly statically typed language such as Java or C++, are often astonished to see that a Scala program that compiles has a much higher probability of being correct on the first run.

IntelliJ can automatically add the inferred type to your definitions.
For instance, type val a = 3 in the Scala console, then move the cursor at the beginning of the a. You should see a light bulb icon. When you click on it, you will see a hint add type annotation to value definition. Click on it, and IntelliJ will add : Int after the a.
Your definition will become val a: Int = 3.

Declaring and calling functions

A Scala function takes 0 to n parameters and returns a value. The type of each parameter must be declared. The type of the returned value is optional, as it is inferred by the Scala compiler when not specified. However, it is a good practice to always specify the return type, as it makes the code more readable:

scala> def presentation(name: String, age: Int): String = 
"Hello, my name is " + name + ". I am " + age + " years old."
presentation: (name: String, age: Int)String

scala> presentation(name = "Bob", age = 25)
res1: String = Hello, my name is Bob. I am 25 years old.

scala> presentation(age = 25, name = "Bob")

res2: String = Hello, my name is Bob. I am 25 years old.

We can call a function by passing arguments in the right order, but we can also name the arguments and pass them in any order. It is a good practice to name the arguments when some of them have the same type, or when a function takes many arguments. It avoids passing the wrong argument and improves readability.

Side effects

A function or expression is said to have a side effect when it modifies some state or has some action in the outside world. For instance, printing a string to the console, writing to a file, and modifying a var, are all side effects.

In Scala, all expressions have a type. A statement which performs a side effect is of type Unit. The only value provided by the type Unit is ():

scala> val x = println("hello")
hello
x: Unit = ()

scala> def printName(name: String): Unit = println(name)
printName: (name: String)Unit

scala> val y = {
var a = 1
a = a+1
}
y: Unit = ()

scala> val z = ()
z: Unit = ()

A pure function is a function whose result depends only on its arguments, and that does not have any observable side effect. Scala allows you to mix side-effecting code with pure code, but it is a good practice to push side-effecting code to the boundaries of your application. We will talk about this later in more detail in the Ensuring referential transparency section in Chapter 3, Handling Errors.

Good practice: When a function with no parameters has side effects, you should declare it and call it with empty brackets (). It informs users of your function that it has side effects. Conversely, a pure function with no parameters should not have empty brackets, and should not be called with empty brackets. IntelliJ helps you in keeping some consistency: it will display a warning if you call a parameterless function with (), or if you omit the () when you call a function declared with ().

Here is an example of a method call with a side effect where we have to use empty brackets, and an example of a pure function:

scala> def helloWorld(): Unit = println("Hello world")
helloWorld: ()Unit

scala> helloWorld()
Hello world

scala> def helloWorldPure: String = "Hello world"
helloWorldPure: String

scala> val x = helloWorldPure
x: String = Hello world

If...else expression

In Scala, if (condition) ifExpr else if ifExpr2 else elseExpr is an expression, and has a type. If all sub-expressions have a type A, the type of the if ... else expression will be A as well:

scala> def agePeriod(age: Int): String = {
if (age >= 65)
"elderly"
else if (age >= 40 && age < 65)
"middle aged"
else if (age >= 18 && age < 40)
"young adult"
else
"child"
}
agePeriod: (age: Int)String

 If sub-expressions have different types, the compiler will infer a common super-type, or widen the type if it is a numeric type:

scala> val ifElseWiden = if (true) 2: Int else 2.0: Double
ifElseWiden: Double = 2.0

scala> val ifElseSupertype = if (true) 2 else "2"
ifElseSupertype: Any = 2

In the first expression present in the preceding code, the first sub-expression is of type Int and the second is of type Double. The type of ifElseWiden is widened to be Double.

In the second expression, the type of ifElseSupertype is Any, which is the common super-type for Int and String.

An if without an else is equivalent to if (condition) ifExpr else (). It is better to always specify the else expression, otherwise, the type of the if/else expression might not be the one we expect:

scala> val ifWithoutElse = if (true) 2
ifWithoutElse: AnyVal = 2

scala> val ifWithoutElseExpanded = if (true) 2: Int else (): Unit
ifWithoutElseExpanded: AnyVal = 2

scala> def sideEffectingFunction(): Unit = if (true) println("hello world")
sideEffectingFunction: ()Unit

In the preceding code, the common super-type between Int and Unit is AnyVal. This can be a bit surprising. In most situations, you would want to avoid that. 

Class

We mentioned earlier that all Scala expressions have a type. A class is a sort of template that can create objects of a specific type. When we want to obtain a value of a certain type, we can instantiate a new object using new followed by the class name:

scala> class Robot
defined class Robot

scala> val nao = new Robot
nao: Robot = Robot@78318ac2

The instantiation of an object allocates a portion of heap memory in the JVM. In the preceding example, the value nao is actually a reference to the portion of heap memory that keeps the content of our new Robot object. You can observe that when the Scala console printed the variable nao, it outputted the name of the class, followed by @78318ac2. This hexadecimal number is, in fact, the memory address of where the object is stored in the heap.

The eq operator can be handy to check if two references are equal. If they are equal, this means that they point to the same portion of memory:

scala> val naoBis = nao
naoBis: Robot = Robot@78318ac2

scala> nao eq naoBis
res0: Boolean = true

scala> val johnny5 = new Robot
johnny5: Robot = Robot@6b64bf61

scala> nao eq johnny5
res1: Boolean = false

A class can have zero to many members. A member can be either:

  • An attribute, also called a field. It is a variable whose content is unique to each instance of the class.
  • A method. This is a function that can read and/or write the attributes of the instance. It can have additional parameters.

Here is a class that defines a few members:

scala> class Rectangle(width: Int, height: Int) {
val area: Int = width * height
def scale(factor: Int): Rectangle = new Rectangle(width * factor, height * factor)
}
defined class Rectangle

The attributes declared inside the brackets () are a bit special: they are constructor arguments, which means that their value must be specified when we instantiate a new object of the class. The other members must be defined inside the curly brackets {}. In our example, we defined four members:

  • Two attributes that are constructor arguments: width and height.
  • One attribute, area. Its value is defined when an instance is created by using the other attributes.
  • One method, scale, which uses the attributes to create a new instance of the class Rectangle.

You can call a member on an instance of a class by using the postfix notation myInstance.member. Let's create a few instances of our class and try to call the members:

scala> val square = new Rectangle(2, 2)
square: Rectangle = Rectangle@2af9a5ef

scala> square.area
res0: Int = 4

scala> val square2 = square.scale(2)
square2: Rectangle = Rectangle@8d29719

scala> square2.area
res1: Int = 16

scala> square.width
<console>:13: error: value width is not a member of Rectangle
square.width

We can call the members area and scale, but not width. Why is that?

This is because, by default, constructor arguments are not accessible from the outside world. They are private to the instance and can only be accessed from the other members. If you want to make the constructor arguments accessible, you need to prefix them with val:

scala> class Rectangle(val width: Int, val height: Int) {
val area: Int = width * height
def scale(factor: Int): Rectangle = new Rectangle(width * factor, height * factor)
}
defined class Rectangle

scala> val rect = new Rectangle(3, 2)
rect: Rectangle = Rectangle@3dbb7bb

scala> rect.width
res3: Int = 3

scala> rect.height
res4: Int = 2

This time, we can get access to the constructor arguments. Note that you can declare attributes using var instead of val. This would make your attribute modifiable. However, in functional programming, we avoid mutating variables. A var attribute in a class is something that should be used cautiously in specific situations. An experienced Scala programmer would flag it immediately in a code review and its usage should be always justified in a code comment.

If you need to modify an attribute, it is better to return a new instance of the class with the modified attribute, as we did in the preceding Rectangle.scale method.

You might worry that all these new objects will consume too much memory. Fortunately, the JVM has a mechanism known as the garbage collector. It automatically frees up the memory used by objects that are not referenced by any variable.

Using the worksheet

IntelliJ offers another handy tool to experiment with the language: the Scala worksheet.

Go to File | New | Scala Worksheet. Name it worksheet.sc. You can then enter some code on the left-hand side of the screen. A red/green indicator in the top right corner shows you if the code you are typing is valid or not. As soon as it compiles, the results appear on the right-hand side:

You will notice that nothing gets evaluated until your whole worksheet compiles.

Class inheritance

Scala classes are extensible. You can extend an existing class to inherit from all its members. If B extends A, we say that B is a subclass of A, a derivation of B, or a specialization of B. A is a superclass of B or a generalization of B.

Let's see how it works in an example. Type the following code in the worksheet:

class Shape(val x: Int, val y: Int) {
val isAtOrigin: Boolean = x == 0 && y == 0
}

class Rectangle(x: Int, y: Int, val width: Int, val height: Int)
extends Shape(x, y)

class Square(x: Int, y: Int, width: Int)
extends Rectangle(x, y, width, width)

class Circle(x: Int, y: Int, val radius: Int)
extends Shape(x, y)

val rect = new Rectangle(x = 0, y = 3, width = 3, height = 2)
rect.x
rect.y
rect.isAtOrigin
rect.width
rect.height

The classes Rectangle and Circle are subclasses of Shape. They inherit from all the members of Shape: x, y, and isAtOrigin. This means that when I instantiate a new Rectangle, I can call members declared in Rectangle, such as width and height, and I can also call members declared in Shape.

When declaring a subclass, you need to pass the constructor arguments of the superclass, as if you were instantiating it. As Shape declares two constructor parameters, x and y, we have to pass them in the declaration extends Shape(x, y). In this declaration, x and y are themselves the constructor arguments of Rectangle. We just passed these arguments up the chain.

Notice that in the subclasses, the constructor parameters x and y are declared without val. If we had declared them with val, they would have been promoted as publicly available attributes. The problem is that Shape also has x and y as public attributes. In this situation, the compiler would have raised a compilation error to highlight the conflict.

Subclass assignment

Consider two classes, A and B, with B extends A.

When you declare a variable of type A, you can assign it to an instance of B, with val a: A = new B.

On the other hand, if you declare a variable of type B, you cannot assign it to an instance of A.

Here is an example that uses the same Shape and Rectangle definitions that were described earlier:

val shape: Shape = new Rectangle(x = 0, y = 3, width = 3, height = 2)
val rectangle: Rectangle = new Shape(x = 0, y = 3)

The first line compiles because Rectangle is a Shape.

The second line does not compile, because not all shapes are rectangles.

Overriding methods

When you derive a class, you can override the members of the superclass to provide a different implementation. Here is an example that you can retype in a new worksheet:

class Shape(val x: Int, val y: Int) {
def description: String = s"Shape at (" + x + "," + y + ")"
}

class Rectangle(x: Int, y: Int, val width: Int, val height: Int)
extends Shape(x, y) {
override def description: String = {
super.description + s" - Rectangle " + width + " * " + height
}
}

val rect = new Rectangle(x = 0, y = 3, width = 3, height = 2)
rect.description

When you run the worksheet, it evaluates and prints the following description on the right-hand side:

res0: String = Shape at (0,3) - Rectangle 3 * 2

We defined a method description on the class Shape that returns a String. When we call rect.description, the method called is the one defined in the class Rectangle, because Rectangle overrides the method description with a different implementation.

The implementation of description in the class Rectangle refers to super.description. super is a keyword that lets you use the members of the superclass without taking into account any overriding. In our case, this was necessary so that we could use the super reference, otherwise, description would have called itself in an infinite loop!

On the other hand, the keyword this allows you to call the members of the same class. Change Rectangle to add the following methods:

class Rectangle(x: Int, y: Int, val width: Int, val height: Int)
extends Shape(x, y) {
override def description: String = {
super.description + s" - Rectangle " + width + " * " + height
}

def descThis: String = this.description
def descSuper: String = super.description
}

val rect = new Rectangle(x = 0, y = 3, width = 3, height = 2)
rect.description
rect.descThis
rect.descSuper

When you evaluate the worksheet, it prints the following strings:

res0: String = Shape at (0,3) - Rectangle 3 * 2
res1: String = Shape at (0,3) - Rectangle 3 * 2
res2: String = Shape at (0,3)

The call to this.description used the definition of description, as declared in the class Rectangle, whereas the call to super.description used the definition of description, as declared in the class Shape.

Abstract class

An abstract class is a class that can have many abstract members. An abstract member defines only a signature for an attribute or a method, without providing any implementation. You cannot instantiate an abstract class: you must create a subclass that implements all the abstract members.

Replace the definition of Shape and Rectangle in the worksheet as follows:

abstract class Shape(val x: Int, val y: Int) {
val area: Double
def description: String
}

class Rectangle(x: Int, y: Int, val width: Int, val height: Int)
extends Shape(x, y) {

val area: Double = width * height

def description: String =
"Rectangle " + width + " * " + height
}

Our class Shape is now abstract. We cannot instantiate a Shape class directly anymore: we have to create an instance of Rectangle or any of the other subclasses of Shape. Shape defines two concrete members, x and y, and two abstract members, area and description. The subclass, Rectangle, implements the two abstract members.

You can use the prefix override when implementing an abstract member, but it is not necessary. I recommend not adding it to keep the code less cluttered. Also, if you subsequently implement the abstract method in the superclass, the compiler will help you find all subclasses that had an implementation. It will not do this if they use override

Trait

A trait is similar to an abstract class: it can declare several abstract or concrete members and can be extended. It cannot be instantiated. The difference is that a given class can only extend one abstract class, however, it can mixin one to many traits. Also, a trait cannot have constructor arguments.

For instance, we can declare several traits, each declaring different abstract methods, and mixin them all in the Rectangle class:

trait Description {
def description: String
}

trait Coordinates extends Description {
def x: Int
def y: Int

def description: String =
"Coordinates (" + x + ", " + y + ")"
}

trait Area {
def area: Double
}

class Rectangle(val x: Int,
val y: Int,
val width: Int,
val height: Int)
extends Coordinates with Description with Area {

val area: Double = width * height

override def description: String =
super.description + " - Rectangle " + width + " * " + height
}

val rect = new Rectangle(x = 0, y = 3, width = 3, height = 2)
rect.description

The following string gets printed when evaluating rect.description:

res0: String = Coordinates (0, 3) - Rectangle 3 * 2

The class Rectangle mixes in the traits Coordinates, Description, and Area. We need to use the keyword extends before trait or class, and the keyword with for all subsequent traits.

Notice that the Coordinates trait also mixes the Description trait, and provides a default implementation. As we did when we had a Shape class, we override this implementation in Rectangle, and we can still call super.description to refer to the implementation of description in the trait Coordinates.

Another interesting point is that you can implement an abstract method with val – in trait Area, we defined def area: Double, and implemented it in Rectangle using val area: Double. It is a good practice to define abstract members with def. This way, the implementer of the trait can decide whether to define it by using a method or a variable.

Scala class hierarchy

All Scala types extend a built-in type called Any. This type is the root of the hierarchy of all Scala types. It has two direct subtypes:

  • AnyVal is the root class of all value types. These types are represented as primitive types in the JVM.
  • AnyRef is the root class of all object types. It is an alias for the class java.lang.Object.
  • A variable of type AnyVal directly contains the value, whereas a variable of type AnyRef contains the address of an object stored somewhere in memory.

The following diagram shows a partial view of this hierarchy:

When you define a new class, it indirectly extends AnyRef. This being an alias for java.lang.Object, your class inherits from all the default methods implemented in Object. Its most important methods are as follows:

  • def toString: String returns a string representation of an object. This method is called whenever you print an object using println. The default implementation returns the class's name followed by the address of the object in memory.
  • def equals(obj: Object): Boolean returns true if the object is equal to another object, and false otherwise. This method is called whenever you compare two objects using ==. The default implementation only compares the objects' references, and hence is equivalent to eq. Fortunately, most classes from the Java and Scala SDK override this method to provide a good comparison. For instance, the class java.lang.String overrides the equals method to compare the content of the strings, character by character. Therefore, when you compare two strings with ==, the result will be true if the strings are the same, even if they are stored in different places in memory.
  • def hashCode: Int is called whenever you put an object in Set or if you use it as a key in Map. The default implementation is based on the address of the object. You can override this method if you want to have a better distribution of the data in Set or Map, which can improve the performance of these collections. However, if you do so, you must make sure that hashCode is consistent with equals: if two objects are equal, their hashCodes must also be equal.

It would be very tedious to have to override these methods for all your classes. Fortunately, Scala offers a special construct called case class that will automatically override these methods for us.

Case class

In Scala, we define most data structures using case classes. case class has one to many immutable attributes and provides several built-in functions compared to a standard class.

Type the following into the worksheet:

case class Person(name: String, age: Int)
val mikaelNew = new Person("Mikael", 41)
// 'new' is optional
val mikael = Person("Mikael", 41)
// == compares values, not references
mikael == mikaelNew
// == is exactly the same as .equals
mikael.equals(mikaelNew)

val name = mikael.name

// a case class is immutable. The line below does not compile:
//mikael.name = "Nicolas"
// you need to create a new instance using copy
val nicolas = mikael.copy(name = "Nicolas")

In the preceding code, the text following // is a comment that explains the preceding statement.

When you declare a class as case class, the Scala compiler automatically generates a default constructor, an equals and hashCode method, a copy constructor, and an accessor for each attribute.

Here is a screenshot of the worksheet we have. You can see the results of the evaluations on the right-hand side:

Companion object

A class can have a companion object. It must be declared in the same file as the class, using the keyword object followed by the name of the class it is accompanying. A companion object is a singleton – there is only one instance of this object in the JVM. It has its own type and is not an instance of the accompanied class.

This object defines static functions or values that are closely related to the class it is accompanying. If you are familiar with Java, it replaces the keyword static: in Scala, all static members of a class are declared inside the companion object.

Some functions in the companion object have a special meaning. Functions named apply are constructors of the class. The name apply can be omitted when we call them:

case class City(name: String, urbanArea: Int)
object City {
val London = City("London", 1738)
val Lausanne = City("Lausanne", 41)
}

case class Person(firstName: String, lastName: String, city: City)
object Person {
def apply(fullName: String, city: City): Person = {
val splitted = fullName.split(" ")
new Person(firstName = splitted(0), lastName = splitted(1), city = city)
}
}

// Uses the default apply method
val m1 = Person("Mikael", "Valot", City.London)
// Call apply with fullName
val m2 = Person("Mikael Valot", City.London)
// We can omit 'apply'
val n = Person.apply("Nicolas Jorand", City.Lausanne)

In the preceding code, we defined a companion object for the class City, which defines some constants. The convention for constants is to have the first letter in uppercase.

The companion object for the class Person defines an additional apply function that acts as a constructor. Its implementation calls the method split(" "), which splits a string separated by spaces to produce an array of type string. It allows us to construct a Person instance using a single string where the first name and last name are separated by a space. We then demonstrated that we can either call the default apply function that comes with the case class, or the one we implemented.

Creating my first project

As you now know the basics of running code in the REPL and the worksheet, it is time to create your first 'Hello World' project. In this section, we are going to filter a list of people and print their name and age into the console.

Creating the project

Repeat the same recipe that you completed in the Installing IntelliJ section to create a new project. Here is a summary of the tasks you must complete:

  1. Run IntelliJ and select Create New Project
  2. Select Scala and sbt
  3. Input the name of the project, such as Examples
  4. If the selected directory doesn't exist, IntelliJ will ask you if you want to create it – select OK

As soon as you accept that you are going to create the directory, IntelliJ is going to download all the necessary dependencies and build the project structure. Be patient, as this could take a while, especially if you do not have a good internet connection.

Once everything is downloaded, you should have your IDE in the following state:

Notice the folder structure. The source code is under src/main/scala and the test code is under src/test/scala. If you have used Maven before, this structure should sound familiar.

Creating the Main object

Here we are! Let's create our first application. First, create the entry point for the program. If you are coming from Java, it would be equivalent to defining the public static void main(String[] args).

Right-click on the src/main/scala folder and select New | Scala Class. Give Main as the class name and Object as the Kind:

We have created our first object. This object is a singleton. There can be only one instance of it in the JVM. The equivalent in Java would be a static class with static methods.

We would like to use it as the main entry point of our program. Scala provides a convenient class named App that needs to be extended. Let's extend our Main object with that class:

object Main extends App {

}

The App superclass defines a static main method that will execute all the code defined inside your Main object. That's all – we created our first version, which does nothing!

We can now run the program in IntelliJ. Click on the small green triangle in the gutter of the object definition, as follows:

The program gets compiled and executed, as shown in the following screenshot:

It is not spectacular, but let's improve it. To get the right habits, we are going to use the TDD technique to proceed further.

Writing the first unit test

TDD is a very powerful technique to write efficient, modular, and safe programs. It is very simple, and there are only three rules to play this game:

  1. You are not allowed to write any production code unless it is to make a failing unit test pass.
  2. You are not allowed to write any more of a unit test than is sufficient to fail, and compilation failures are failures.
  3. You are not allowed to write any more production code than is sufficient to pass the one failing unit test.
See the full article from Uncle Bob here: http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd.

There are multiple testing frameworks in Scala, but we chose ScalaTest (http://www.scalatest.org/) for its simplicity.

In order to add the ScalaTest library in the project, follow these steps:

  1. Edit the build.sbt file.
  2. Add a new repository resolver to search for Scala libraries.
  3. Add the ScalaTest library:
name := "Examples"
version := "0.1"
scalaVersion := "2.12.4"
resolvers += "Artima Maven Repository" at "http://repo.artima.com/releases"
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.4" % "test"
Notice the information bar on the top of the screen. It tells you that your file has changed and asks for multiple choices. As this is a small project, you can select enable autoimport.
  1. Create the test class by right-clicking on the test/scala folder and clicking on create a new class. Name it MainSpec.

ScalaTest offers multiple ways to define your test – the full list can be found on the official website (http://www.scalatest.org/at_a_glance/WordSpec). We are going to use the WordSpec style since it is quite prescriptive, offers a hierarchical structure, and is commonly used on large Scala projects.

Your MainSpec should extend the WordSpec class and the Matchers class, like so:

class MainSpec extends WordSpec with Matchers {

}
The class Matchers is providing the word should as a keyword to perform the comparison on a test.

WordSpec and Matchers are underlined in red, which means that the class is not resolved. To make it resolved, go with the cursor on the class and press Alt + Enter of your keyboard. If you are positioned on the WordSpec word, a popup should appear. This is normal, as there are several classes named WordSpec in different packages:

Select the first option and IntelliJ will automatically add the import on the top of your code. On the Matchers class, as soon as you type Alt + Enter, the import will be added directly.

The final code should be as follows:

import org.scalatest.{WordSpec, Matchers}

class MainSpec extends WordSpec with Matchers {

}

Our class skeleton is now ready for our first test. We would like to create the Person class and test its constructor.

Let's explain what we would like to test using simple sentences. Complete the test class with the following code:

class MainSpec extends WordSpec with Matchers {
"A Person" should {
"be instantiated with a age and name" in {
val john = Person(firstName = "John", lastName = "Smith", 42)
john.firstName should be("John")
john.lastName should be("Smith")
john.age should be(42)
}
}
}

IntelliJ is complaining that it cannot resolve the symbols Person, name, surname, and age. This is expected since the Person class does not exist. Let's create it in the folder src/main/scala. Right-click on the folder and create a new class named Person.

Transform it in the case of the class by adding the case keyword and defining the constructor with the name, surname, and age:

case class Person(firstName: String, lastName: String, age: Int)

If you go back to the MainSpec.scala file, you'll notice that the class is now compiled without any error and warning. The green tick () on the top-right of the code window confirms this.

Run the test by right-clicking on the MainSpec.scala file and selecting Run 'MainSpec', or use the keyboard shortcut Ctrl + Shift + F10 or Ctrl + Shift + R:

The test contained in MainSpec runs and the results appear in the Run window:

Implementing another feature

Now, we would like to have a nice representation of the person by stating his/her name and age. The test should look like the following:

"Get a human readable representation of the person" in {
val paul = Person(firstName = "Paul", lastName = "Smith", age = 24)
paul.description should be("Paul Smith is 24 years old")
}

Run the test again. We will get a compilation error:

This is expected as the function doesn't exist on the Person class. To implement it, add the expected implementation by setting the cursor on the description() error in the MainSpec.scala class, hitting Alt + Enter, and selecting the create method description.
IntelliJ generates the method for you and sets the implementation to ???. Replace ??? with the expected code:

def description = s"$firstName $lastName is $age ${if (age <= 1) "year"                    else "years"} old"

By doing so, we defined a method that does not take any parameter and return a string representing Person. In order to simplify the code, we are using a string interpolation to build the string. To use string interpolation, you just have to prepend an s before the first quote. Inside the quote, you can use the wildcard $ so that we can use an external variable and use the bracket after the dollar sign to enter more code than just a variable name.

Execute the test and the result should be green:

The next step is to write a utility function that, given a list of people, returns only the adults.

For the tests, two cases are defined:

"The Person companion object" should {
val (akira, peter, nick) = (
Person(firstName = "Akira", lastName = "Sakura", age = 12),
Person(firstName = "Peter", lastName = "Müller", age = 34),
Person(firstName = "Nick", lastName = "Tagart", age = 52)
)
"return a list of adult person" in {
val ref = List(akira, peter, nick)
Person.filterAdult(ref) should be(List(peter, nick))
}
"return an empty list if no adult in the list" in {
val ref = List(akira)
Person.filterAdult(ref) should be(List.empty[Person])
}
}

Here, we used a tuple to define three variables. This is a convenient way to define multiple variables. The scope of the variables is bounded by the enclosing curly brackets.
Use IntelliJ to create the filterAdult function by using the Alt+ Enter shortcut. The IDE understands that the function should be in the Person companion object and generates it for you.

If you didn't use the named parameters and would like to use them, IntelliJ can help you: hit Alt + Enter when the cursor is after the parenthesis and select "used named arguments ...".

We implement this method using the for comprehension Scala feature:

object Person {
def filterAdult(persons: List[Person]) : List[Person] = {
for {
person <- persons
if (person.age >= 18)
} yield (person)
}
}

It is a good practice to define the return type of the method, especially when this method is exposed as a public API.

The for comprehension has been used only for demonstration purposes. We can simplify it using the filter method on List. filter is part of the Scala Collections API and is available for many kinds of collections:

def filterAdult(persons: List[Person]) : List[Person] = {
persons.filter(_.age >= 18)
}

Implementing the Main method

Now that all our tests are green, we can implement the main method. The implementation becomes trivial as all the code is already in the test:

object Main extends App {
val persons = List(
Person(firstName = "Akira", lastName = "Sakura", age = 12),
Person(firstName = "Peter", lastName = "Müller", age = 34),
Person(firstName = "Nick", lastName = "Tagart", age = 52))

val adults = Person.filterAdult(persons)
val descriptions = adults.map(p => p.description).mkString("\n\t")
println(s"The adults are \n\t$descriptions")
}

The first thing is to define a list of Person, so that Person.filterAdult() is used to remove all the persons, not the adults. The adults variable is a list of Person, but I would like to transform this list of Person into a list of the description of the Person. To perform this operation, the map function of the collection is used. The map function transforms each element of the list by applying the function in the parameter.

The notation inside the map() function defines an anonymous function that takes p as the parameter. The body of the function is p.description. This notation is commonly used whenever a function takes another function as an argument.

Once we have a list of descriptions, we create a string with the mkString() function. It concatenates all the elements of the list using the special character \n\t, which are respectively the carriage return and the tab character.

Finally, we perform the side effect, which is the print on the console. To print in the console, the println alias is used. It is a syntactic sugar for System.out.println.

Summary

We have finished the first chapter, and you should now have the basics to start a project on your own. We covered the installation of an IDE to code in Scala with the basic usage of the dedicated build tool named SBT. Three ways to explore Scala have been demonstrated, including the REPL to test simple Scala features, the IntelliJ worksheet to play with a small environment, and lastly a real project.

To code our first project, we used ScalaTest and the TDD methodology so that we had good code quality from the beginning. 

In the next chapter, we will write a complete program. It is a financial application that allows its users to estimate when they can retire. We will keep using the TDD technique and will further explore the Scala language, its development kit, and their best practices. 

Left arrow icon Right arrow icon
Download code icon Download Code

Key benefits

  • Develop Scala projects on topics ranging from web applications to big data analysis
  • Unleash the full power of modern web programming using Play Framework
  • Build real-time data pipelines in Scala with a Bitcoin transaction analysis app

Description

Scala Programming Projects is a comprehensive project-based introduction for those who are new to Scala. Complete with step-by-step instructions and easy-to-follow tutorials that demonstrate best practices when building applications, this Scala book will have you building real-world projects in no time. Starting with the fundamentals of software development, you’ll begin with simple projects, such as developing a financial independence calculator, and then advance to more complex projects, such as a building a shopping application and a Bitcoin transaction analyzer. You’ll explore a variety of Scala features, including its OOP and FP capabilities, and learn how to write concise, reactive, and concurrent applications in a type-safe manner. You’ll also understand how to use libraries such as Akka and Play. Furthermore, you’ll be able to integrate your Scala apps with Kafka, Spark, and Zeppelin, along with deploying applications on a cloud platform. By the end of the book, you’ll have a firm foundation in Java programming that’ll enable you to solve a variety of real-world problems, and you’ll have built impressive projects to add to your professional portfolio.

Who is this book for?

If you’re new to programming and want to learn how to use Scala, this book is for you. Though not necessary, some knowledge of Java will help you understand the concepts covered in this book.

What you will learn

  • Build, test, and package code using sbt (Scala Build Tool)
  • Decompose code into functions, classes, and packages for maintainability
  • Implement the functional programming capabilities of Scala
  • Develop a simple CRUD REST API using Play Framework
  • Access a relational database using Slick
  • Develop a dynamic web UI using Scala.js
  • Source streaming data using Spark Streaming and write a Kafka producer
  • Use Spark and Zeppelin to analyze data
Estimated delivery fee Deliver to Belgium

Premium delivery 7 - 10 business days

€17.95
(Includes tracking information)

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Sep 29, 2018
Length: 398 pages
Edition : 1st
Language : English
ISBN-13 : 9781788397643
Category :
Languages :
Tools :

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Estimated delivery fee Deliver to Belgium

Premium delivery 7 - 10 business days

€17.95
(Includes tracking information)

Product Details

Publication date : Sep 29, 2018
Length: 398 pages
Edition : 1st
Language : English
ISBN-13 : 9781788397643
Category :
Languages :
Tools :

Packt Subscriptions

See our plans and pricing
Modal Close icon
€18.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
€189.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts
€264.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total 120.97
Scala Design Patterns
€36.99
Scala Programming Projects
€41.99
Modern Scala Projects
€41.99
Total 120.97 Stars icon
Banner background image

Table of Contents

12 Chapters
Writing Your First Program Chevron down icon Chevron up icon
Developing a Retirement Calculator Chevron down icon Chevron up icon
Handling Errors Chevron down icon Chevron up icon
Advanced Features Chevron down icon Chevron up icon
Type Classes Chevron down icon Chevron up icon
Online Shopping - Persistence Chevron down icon Chevron up icon
Online Shopping - REST API Chevron down icon Chevron up icon
Online Shopping - User Interface Chevron down icon Chevron up icon
Interactive Browser Chevron down icon Chevron up icon
Fetching and Persisting Bitcoin Market Data Chevron down icon Chevron up icon
Batch and Streaming Analytics Chevron down icon Chevron up icon
Other Books You May Enjoy Chevron down icon Chevron up icon

Customer reviews

Rating distribution
Full star icon Full star icon Full star icon Half star icon Empty star icon 3.8
(5 Ratings)
5 star 40%
4 star 20%
3 star 20%
2 star 20%
1 star 0%
Melvin Apr 03, 2021
Full star icon Full star icon Full star icon Full star icon Full star icon 5
This is in my opinion the best scala book out there to start your journey with. I have looked at quite a few scala books and some are good but take forever to get to so called advanced concepts. This book gets you up to speed with programming concepts unique to scala without needing to read over a thousand pages first. Additionally, this book incorporated the use of intellij IDE which can be a pain when you first start using scala. The other thing that I liked about the book is that the projects show you how to tackle various problems by writing in the scala style of the functional programming. I think this book probably was the most useful scala book I have ever bought.
Amazon Verified review Amazon
Misha Tavkhelidze Jan 12, 2019
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Excellent book to start your Scala journey. Read it before jumping to more advanced, say, Functional Programming in Scala.Apart from introducing the language (and FP paradigm) from very basic to comparatively advanced aspects, the book also teaches you how to set up projects using standard build tools and frameworks, which I found to be invaluable for someone who is new to the whole eco-system.Some familiarity with the language itself is nessesary, but, I believe, not required.
Amazon Verified review Amazon
Cameron Smith Sep 03, 2019
Full star icon Full star icon Full star icon Full star icon Empty star icon 4
Good introduction to specific frameworks, approaches and libraries for someone who already knows Scala.Opinionated but justifies his opinions based on realistic project examples, rather than just ranting.Still have not finished the book - because every two pages give a wealth of examples and ideas to try out.
Amazon Verified review Amazon
Amazon Customer Aug 08, 2019
Full star icon Full star icon Full star icon Empty star icon Empty star icon 3
Books does not teach you scala. Project descriptions not best but enough. That is book for people that have learned scala, akka etc and looking for good project example and some example how things are done in scala ecosystem.
Amazon Verified review Amazon
Mark Tanser Jul 09, 2019
Full star icon Full star icon Empty star icon Empty star icon Empty star icon 2
The overall content and exercises are fine, but it is dogged by typos and omissions which render it a huge struggle to follow for a beginner. Without consulting the online code on gitHub it would be impossible to complete the sections. There are also code exceptions and errors which are not covered in the text and you're left to search for answers on Stackoverflow. Really, a book like this should be thoroughly proof-read and tested by a first-sight user going through the instructions cover-to-cover, before committing to print and offering for sale.
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is the delivery time and cost of print book? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
What is custom duty/charge? Chevron down icon Chevron up icon

Customs duty are charges levied on goods when they cross international borders. It is a tax that is imposed on imported goods. These duties are charged by special authorities and bodies created by local governments and are meant to protect local industries, economies, and businesses.

Do I have to pay customs charges for the print book order? Chevron down icon Chevron up icon

The orders shipped to the countries that are listed under EU27 will not bear custom charges. They are paid by Packt as part of the order.

List of EU27 countries: www.gov.uk/eu-eea:

A custom duty or localized taxes may be applicable on the shipment and would be charged by the recipient country outside of the EU27 which should be paid by the customer and these duties are not included in the shipping charges been charged on the order.

How do I know my custom duty charges? Chevron down icon Chevron up icon

The amount of duty payable varies greatly depending on the imported goods, the country of origin and several other factors like the total invoice amount or dimensions like weight, and other such criteria applicable in your country.

For example:

  • If you live in Mexico, and the declared value of your ordered items is over $ 50, for you to receive a package, you will have to pay additional import tax of 19% which will be $ 9.50 to the courier service.
  • Whereas if you live in Turkey, and the declared value of your ordered items is over € 22, for you to receive a package, you will have to pay additional import tax of 18% which will be € 3.96 to the courier service.
How can I cancel my order? Chevron down icon Chevron up icon

Cancellation Policy for Published Printed Books:

You can cancel any order within 1 hour of placing the order. Simply contact [email protected] with your order details or payment transaction id. If your order has already started the shipment process, we will do our best to stop it. However, if it is already on the way to you then when you receive it, you can contact us at [email protected] using the returns and refund process.

Please understand that Packt Publishing cannot provide refunds or cancel any order except for the cases described in our Return Policy (i.e. Packt Publishing agrees to replace your printed book because it arrives damaged or material defect in book), Packt Publishing will not accept returns.

What is your returns and refunds policy? Chevron down icon Chevron up icon

Return Policy:

We want you to be happy with your purchase from Packtpub.com. We will not hassle you with returning print books to us. If the print book you receive from us is incorrect, damaged, doesn't work or is unacceptably late, please contact Customer Relations Team on [email protected] with the order number and issue details as explained below:

  1. If you ordered (eBook, Video or Print Book) incorrectly or accidentally, please contact Customer Relations Team on [email protected] within one hour of placing the order and we will replace/refund you the item cost.
  2. Sadly, if your eBook or Video file is faulty or a fault occurs during the eBook or Video being made available to you, i.e. during download then you should contact Customer Relations Team within 14 days of purchase on [email protected] who will be able to resolve this issue for you.
  3. You will have a choice of replacement or refund of the problem items.(damaged, defective or incorrect)
  4. Once Customer Care Team confirms that you will be refunded, you should receive the refund within 10 to 12 working days.
  5. If you are only requesting a refund of one book from a multiple order, then we will refund you the appropriate single item.
  6. Where the items were shipped under a free shipping offer, there will be no shipping costs to refund.

On the off chance your printed book arrives damaged, with book material defect, contact our Customer Relation Team on [email protected] within 14 days of receipt of the book with appropriate evidence of damage and we will work with you to secure a replacement copy, if necessary. Please note that each printed book you order from us is individually made by Packt's professional book-printing partner which is on a print-on-demand basis.

What tax is charged? Chevron down icon Chevron up icon

Currently, no tax is charged on the purchase of any print book (subject to change based on the laws and regulations). A localized VAT fee is charged only to our European and UK customers on eBooks, Video and subscriptions that they buy. GST is charged to Indian customers for eBooks and video purchases.

What payment methods can I use? Chevron down icon Chevron up icon

You can pay with the following card types:

  1. Visa Debit
  2. Visa Credit
  3. MasterCard
  4. PayPal
What is the delivery time and cost of print books? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela