How to Find Type of Variable in Scala

Suraj P Feb 02, 2024
  1. Use Pattern Matching in Scala
  2. Use the getClass Method in Scala
  3. Use Manifest in Scala
  4. Use TypeTag in Scala
  5. Use Type Checking (isInstanceOf) in Scala
  6. Conclusion
How to Find Type of Variable in Scala

This article will teach how to find the type of variable in Scala. Let’s see different methods to get the type of a variable in Scala at runtime.

Use Pattern Matching in Scala

Pattern matching is a fundamental feature of Scala that enables sophisticated branching based on the structure of data. It allows you to define different cases, each matching a particular pattern, and execute corresponding logic based on the match.

In the context of determining variable types, we can use pattern matching to match against types and take appropriate actions accordingly.

Let’s begin with a basic example of pattern matching to determine the type of a variable. Suppose we have a variable data of type Any whose type we want to ascertain.

def getType(data: Any): String = data match {
  case _: String => "String"
  case _: Int => "Int"
  case _: Double => "Double"
  case _ => "Unknown type"
}

val variable1: Any = "hello"
val variable2: Any = 42
val variable3: Any = 3.14

println(getType(variable1))
println(getType(variable2))
println(getType(variable3))

Output:

String
Int
Double

The provided code begins by defining a method named getType that takes an argument data of type Any. This method employs pattern matching to determine the type of input data.

If the input matches the pattern of String, it returns "String". If it matches Int, it returns "Int".

If it matches Double, it returns "Double". If there is no match, denoted by the wildcard _, it returns "Unknown type".

Subsequently, three variables are declared and initialized of type Any: variable1 holds a string, variable2 is an integer, and variable3 is a double. The println statements then invoke the getType method with each of these variables as arguments, showcasing the type detection functionality.

For variable1, it prints String since it matches the String case in the getType method. For variable2, it prints Int as it matches the Int case, and for variable3, it prints Double since it matches the Double case.

Pattern Matching for Custom Types

Pattern matching is not limited to built-in types. You can also use it to match custom types and perform actions accordingly. Here’s an example of pattern matching with custom types:

sealed trait Animal
case class Dog(name: String) extends Animal
case class Cat(name: String) extends Animal

def displayAnimal(animal: Animal): Unit = animal match {
  case Dog(name) => println(s"Dog named $name")
  case Cat(name) => println(s"Cat named $name")
}

val myDog: Animal = Dog("Buddy")
val myCat: Animal = Cat("Fluffy")

displayAnimal(myDog)
displayAnimal(myCat)

Output:

Dog named Buddy
Cat named Fluffy

In this example, we define a hierarchy of animals using case classes and a sealed trait. We then use pattern matching to determine the type of the animal and display information accordingly.

Use the getClass Method in Scala

The getClass method in Scala is inherited from the Object class, which is the base class for all objects. This method provides information about the runtime class of an object, allowing us to identify the type of the variable it represents.

When invoked on a variable, it returns an instance of the Class type, providing details about the class or type of the object.

Let’s start with a basic example to understand how to use the getClass method to determine the type of a variable.

object TypeDetectionApp extends App {
  val variable1: String = "Hello, Scala!"
  val variable2: Int = 42
  val variable3: Double = 3.14

  println("Type of variable1: " + variable1.getClass.getSimpleName)
  println("Type of variable2: " + variable2.getClass.getSimpleName)
  println("Type of variable3: " + variable3.getClass.getSimpleName)
}

The output will be:

Type of variable1: String
Type of variable2: Integer
Type of variable3: Double

As we can see, within the TypeDetectionApp object, three variables are declared and initialized with specific types: variable1 of type String, variable2 of type Int, and variable3 of type Double. Each of these variables holds a string, an integer, and a double value, respectively.

Subsequently, the code uses the getClass method on each variable to retrieve the runtime class of the variable. The getSimpleName method is then applied to obtain the simple (unqualified) name of the class, representing the type of the variable.

The println statements display the types of the variables using the simple names obtained through getClass.getSimpleName.

Use getClass With Custom Types

The getClass method is not limited to built-in types; it also works with custom types. Let’s see an example where we define a custom class and use getClass to determine its type.

class CustomType

object TypeDetectionApp extends App {
  val customObject = new CustomType

  println("Type of customObject: " + customObject.getClass.getSimpleName)
}

Output:

Type of customObject: CustomType

In this example, we create an instance of a custom class CustomType and use the getClass method to determine its runtime class, effectively identifying its type.

Simplify Type Output With getSimpleName

The output of the getClass method often includes the fully qualified class name, which might not be very readable. For instance,

object MyClass {
    def main(args: Array[String]) {
		val x = 123;
		System.out.println(x.getClass)

		val y = "hero"
		System.out.println(y.getClass)

		val z = 34.56
		System.out.println(z.getClass)
    }
}

Output:

int
class java.lang.String
double

The output above shows that it prints java.lang.String when it comes to strings because the Scala string is nothing but a wrapper around java.lang.String.

To enhance readability, we can use the getSimpleName method, which is available on the Class type. This method returns a string representing the simple name of the class (the name without the package).

Here’s an example illustrating the usage of getSimpleName:

object TypeDetectionApp extends App {
  val someString = "Hello, Scala!"

  println("Type of someString: " + someString.getClass.getSimpleName)
}

Output:

Type of someString: String

Therefore, instead of java.lang.String, if we want a String with a more meaningful output, we can use getSimpleName with the getClass method.

Use Manifest in Scala

Manifest is a powerful feature in Scala that provides a way to obtain information about generic types at runtime. It serves as a means to capture the type information of a generic type, enabling us to work with type parameters dynamically.

Let’s start with a basic example to understand how to use Manifest to determine the type of a variable.

object TypeDetectionApp extends App {
  def printType[T](data: T)(implicit manifest: Manifest[T]): Unit = {
    println("Type of data: " + manifest.toString)
  }

  val variable1: Int = 42
  val variable2: String = "Hello, Scala!"

  printType(variable1)
  printType(variable2)
}

Output:

Type of data: Int
Type of data: java.lang.String

Within the TypeDetectionApp object, we have a method named printType[T](data: T)(implicit manifest: Manifest[T]): Unit. This method is parameterized with a generic type T and takes an implicit Manifest[T] as well, which is crucial for obtaining type information at runtime.

Within the method, the type of data is determined using the provided Manifest and printed to the console.

Two variables are then declared: variable1 of type Int with a value of 42, and variable2 of type String with the value "Hello, Scala!". Subsequently, the printType method is invoked with variable1 and variable2 as arguments.

Due to the implicit Manifest, the method is able to ascertain and print the types of variable1 and variable2. Finally, the output of the program displays the types Int and String, corresponding to variable1 and variable2, respectively.

One major advantage of using Manifest is finding the type of non-primitive types, like if a variable is a List or a Sequence etc.

Let’s consider the following example:

object MyClass {

  def myFunc[T: Manifest](t: T): Manifest[T] = manifest[T]

  def main(args: Array[String]): Unit = {
    val y = List(1,2,3,4)
    val z = Seq("apple","mango")

    println(myFunc(y))
    println(myFunc(z))
  }
}

Output:

scala.collection.immutable.List[Int]
scala.collection.immutable.Seq[java.lang.String]

In this example, we use Manifest to obtain the types of a List and a Seq. As shown in the output, we accurately determine the types, demonstrating the utility of Manifest in identifying complex, non-primitive types.

Use Manifest With Custom Types

Manifest also works with custom types. Let’s see an example where we define a custom class and use Manifest to determine its type.

class CustomType

object TypeDetectionApp extends App {
  def printType[T](data: T)(implicit manifest: Manifest[T]): Unit = {
    println("Type of data: " + manifest.toString)
  }

  val customObject = new CustomType

  printType(customObject) // Prints: Type of data: CustomType
}

Output:

Type of data: CustomType

In this example, we create an instance of a custom class CustomType and use Manifest to determine its runtime type, effectively identifying its type.

Use TypeTag in Scala

TypeTag is a part of Scala’s reflection library that provides runtime type information about types and enables the recovery of generic type parameters. When using generics or dealing with polymorphic types, type erasure may strip away type information, making it challenging to work with the types at runtime. TypeTag helps overcome this limitation by capturing the type information even when it would otherwise be erased.

Let’s start with a basic example to understand how to use TypeTag to determine the type of a variable.

import scala.reflect.runtime.universe._

object TypeDetectionApp extends App {
  def printType[T: TypeTag](data: T): Unit = {
    println("Type of data: " + typeOf[T])
  }

  val variable1: Int = 42
  val variable2: String = "Hello, Scala!"

  printType(variable1)
  printType(variable2)
}

Output:

Type of data: Int
Type of data: String

In this example, we define an object named TypeDetectionApp, extending App for standalone execution. Within this object, a method printType[T: TypeTag](data: T) is declared.

This method is parameterized with a type T and has a context bound with TypeTag[T], allowing access to type information at runtime. Inside the method, the typeOf function is employed to retrieve and print the type of the input variable.

Following this, two variables, variable1 of type Int and variable2 of type String, are defined with respective values. The printType method is then invoked with these variables as arguments, enabling the determination and printing of their types.

As we can see, the output demonstrates the successful retrieval of types for variable1 and variable2 as Int and String, respectively.

Use TypeTag With Custom Types

TypeTag can also work with custom types. Let’s see an example where we define a custom class and use TypeTag to determine its type.

import scala.reflect.runtime.universe._

class CustomType

object TypeDetectionApp extends App {
  def printType[T: TypeTag](data: T): Unit = {
    println("Type of data: " + typeOf[T])
  }

  val customObject = new CustomType

  printType(customObject)
}

Output:

Type of data: CustomType

In this example, we create an instance of a custom class CustomType and use TypeTag to determine its runtime type, effectively identifying its type.

Use Type Checking (isInstanceOf) in Scala

Scala provides the isInstanceOf method, which allows you to determine whether an object is an instance of a particular type. This is a form of type checking that enables runtime type detection, allowing you to adapt your program’s behavior based on the actual types of variables and objects.

Let’s start with a basic example to understand how to use isInstanceOf for type checking in Scala.

object TypeDetectionApp extends App {
  val variable1: Any = 42
  val variable2: Any = "Hello, Scala!"

  println("Is variable1 an Int? " + (variable1.isInstanceOf[Int]))
  println("Is variable2 a String? " + (variable2.isInstanceOf[String]))
}

Output:

Is variable1 an Int? true
Is variable2 a String? true

As we can see, two variables are declared: variable1 and variable2, both of type Any. Any is a superclass of all Scala classes and represents the most general type in Scala’s type system, allowing for any type of value to be stored.

The variable1 is assigned the value 42, an integer, while variable2 is assigned the string "Hello, Scala!". Subsequently, the code uses the isInstanceOf method to perform type-checking on these variables.

For variable1, it checks if the variable is an instance of Int, returning true since variable1 indeed holds an integer. For variable2, the code checks if it’s an instance of String, returning true as variable2 holds a string.

The println statements display these results, indicating whether each variable is of the specified type.

Use Type Checking With Custom Types

You can also use type checking to determine if an object is an instance of a custom type. Let’s see an example:

class CustomType

object TypeDetectionApp extends App {
  val customObject = new CustomType

  println("Is customObject an instance of CustomType? " + (customObject.isInstanceOf[CustomType]))
}

Output:

Is customObject an instance of CustomType? true

In this example, we define a custom class CustomType and create an instance of it. We then use isInstanceOf to determine if the object is an instance of CustomType.

Conclusion

We have discussed several methods to determine the type of a variable at runtime in Scala. Choose the appropriate method based on your requirements and the Scala version.

Author: Suraj P
Suraj P avatar Suraj P avatar

A technophile and a Big Data developer by passion. Loves developing advance C++ and Java applications in free time works as SME at Chegg where I help students with there doubts and assignments in the field of Computer Science.

LinkedIn GitHub