Scala Tutorial - Learn How To Use Companion Objects' Apply Method As A Factory (Class Hierarchy Via Inheritance)
Overview
In this tutorial, we will learn how to use the Companion Object's apply() method as a factory to return different class type hierarchies.
The class hierarchies will be created by making use of inheritance using the extends keyword.
This tutorial builds on what you have learned about Companion Objects from the previous tutorial.
Steps
1. How to define a simple class to represent a Donut object
Let's modify the Donut class from the previous tutorial and make the productCode parameter an Option with a default value of None.
println("Step 1: How to define a simple class to represent a Donut object")
class Donut(name: String, productCode: Option[Long] = None){
def print = println(s"Donut name = $name, productCode = ${productCode.getOrElse(0)}")
}
NOTE:
- You can refer to the tutorial on How To Use Option if you are not familiar with Option in Scala.
2. How to declare class hierarchy through inheritance using extends keyword
If you have used an Object Oriented programming language in the past like Java or .NET, you will be familiar with creating class hierarchies with inheritance using the extends keyword.
With inheritance in mind, let's create two sub-classes of the Donut class name GlazedDonut and VanillaDonut respectively.
println("\nStep 2: How to declare class hierarchy through inheritance using extends keyword")
class GlazedDonut(name: String) extends Donut(name)
class VanillaDonut(name: String) extends Donut(name)
NOTE:
- As a reminder from the Scala Introduction Tutorial, Scala is both a Functional Programming Language and an Object Oriented Language.
3. How to declare apply method of companion object as a factory
To keep this example simple, we make use of Pattern Matching in the apply() method to return either a GlazedDonut or VanillaDonut type.
println("\nStep 3: How to declare apply method of companion object as a factory")
object Donut {
def apply(name: String): Donut = {
name match {
case "Glazed Donut" => new GlazedDonut(name)
case "Vanilla Donut" => new VanillaDonut(name)
case _ => new Donut(name)
}
}
}
NOTE:
- To keep the example simple, we also use the wildcard _ to return a new Donut type for anything that is not a Glazed or Vanilla Donut.
4. How to call apply method of companion object which is a factory
Calling the Donut's apply() factory method is not different than calling the Donut Companion Object.
println("\nStep 4: How to call apply method of companion object which is a factory")
val glazedDonut = Donut("Glazed Donut")
println(s"The class type of glazedDonut = ${glazedDonut.getClass}")
glazedDonut.print
val vanillaDonut = Donut("Vanilla Donut")
println(s"The class type of vanillaDonut = ${vanillaDonut.getClass}")
vanillaDonut.print
You should see the following output when you run your Scala application in IntelliJ:
Step 4: How to call apply method of companion object which is a factory
The class type of glazedDonut = class com.allaboutscala.chapter.four.CompanionObjectAsFactory_Tutorial$GlazedDonut
Donut name = Glazed Donut, productCode = 0
The class type of vanillaDonut = class com.allaboutscala.chapter.four.CompanionObjectAsFactory_Tutorial$VanillaDonut
Donut name = Vanilla Donut, productCode = 0
Summary
In this tutorial, we went over the following:
- How to define a simple class to represent a Donut object
- How to declare class hierarchy through inheritance using extends keyword
- How to declare apply method of companion object as a factory
- How to call apply method of companion object which is a factory
Tip
- In upcoming tutorials, we will go over case classes which is a feature of Scala that will help you reduce boiler plate code by automatically generating accessors functions, hashCode and equals() methods.
- What is more, case classes will also create companion objects for you!
- You can refer to Wikipedia if you are new to the Factory Pattern.
Source Code
The source code is available on the allaboutscala GitHub repository.
What's Next
In the next tutorial, I will show you how to declare values and fields inside Companion Objects.