In Scala, when you have defined a class with the same name as a singleton object, it is called a companion class, and the singleton object will be called a companion object. The companion object and companion class should be defined in a single file. Companion objects can access the private members and functions of the companion class.
Syntax:
class CompanionDemo {
}
object CompanionDemo {
}
The above image has some symbols on the left of the class and object, which denotes that the class has one companion object declared and the object has a companion class.
Example:
CompanionDemo.scala
class CompanionDemo {
// Variables of Companion class
var str1 = "TGB Learner"
var str2 = "Time to learn Companion Object"
// Method of Companion class
def show():String = {
str1 + "\n" + str2
}
}
object CompanionDemo {
def apply() = {
println("This is companion object")
}
def greet(): String = {
println("This is companion object")
val companionObject = new CompanionDemo
companionObject.show()
}
}
object CompanionExample extends App {
print(CompanionDemo.greet())
}
Output:
This is companion object
TGB Learner
Time to learn Companion Object
Advantages of Companion Objects
1. Companion object and companion class can access private and public members of each other.
For example: If I update the above example a little bit, it will still produce the same output:
CompanionDemo.scala
class CompanionDemo {
// Variables of Companion class
var str2 = "Time to learn Companion Object"
// Method of Companion class
def show():String = {
CompanionDemo.str1 + "\n" + str2 //It is able to access the variable str1
}
}
object CompanionDemo {
var str1 = "TGB Learner" // str1 defined in companion object now
def apply() = {
println("This is companion object")
}
def greet(): String = {
println("This is companion object")
val companionObject = new CompanionDemo
companionObject.show()
}
}
2. Companion object allow you to use the object without the need for the new keyword. For this reason, we can use most of the collections without specifying a new keyword.
For Example:
val listOfString = List("No", "new", "keyword", "required")
// Hence list is also a companion object.
Note: You can use Ctrl+Click on intellij idea IDE to view the definition of how List is created as a companion object
Defining an apply method in a companion object has a special meaning to the Scala compiler. There’s a little syntactic sugar baked into Scala that lets you type this code:
val listExample = List(100, 200)
During the compilation process, the compiler turns that code into the below code:
val p = List.apply(100, 200)
The apply method in the companion object acts as a Factory Method . Scala’s syntactic sugar lets you use the syntax shown, creating new class instances without using the new keyword.
Another Example to demonstrate the above :
User.scala
class User {
var name: Option[String] = None
var age: Option[Int] = None
override def toString = s"$name, $age"
}
object User {
def apply(name: Option[String]): User = {
var p = new User
p.name = name
p
}
def apply(name: Option[String], age: Option[Int]): User = {
val user = new User
user.name = name
user.age = age
user
}
}
UserExample.scala
object UserExample extends App {
val user1 = User(None)
val user2 = User(Some("TGB User"))
val user3 = User(Some("Meet"), Some(26))
println(user1)
println(user2)
println(user3)
}