Scala - Dynamic Invocation



This chapter takes you through the concept of dynamic invocation in Scala programming. Dynamic invocation is that you can call methods on objects dynamically at runtime. It is used when you work with dynamic languages and frameworks that require runtime method resolution.

Dynamic Invocation

You can invoke methods on objects whose types are not known until runtime. This is used when you interact with dynamic languages, scripting languages, APIs, etc. These provide objects with methods not known at compile-time.

Dynamic invocation can be achieved using Dynamic trait. So, objects act like dynamic language objects. It provides method calls and property accesses that are resolved at runtime, rather than statically by the compiler.

Syntax

The syntax for dynamic invocation in Scala using the Dynamic trait -

import scala.language.dynamics

class DynamicExample extends Dynamic {
   def applyDynamic(name: String)(args: Any*): String = {
      s"Called method '$name' with arguments ${args.mkString(", ")}"
   }
}

val example = new DynamicExample
println(example.someMethod(1, 2, 3))  

Example of Dynamic Invocation

The following example shows defining and using dynamic invocation in Scala programming -

import scala.language.dynamics

class DynamicExample extends Dynamic {
   def applyDynamic(name: String)(args: Any*): String = {
      s"Called method '$name' with arguments ${args.mkString(", ")}"
   }
}

object Demo {
   def main(args: Array[String]): Unit = {
      val example = new DynamicExample
      println(example.someMethod(1, 2, 3)) 
   }
}

Save the above program in Demo.scala. Use the following commands to compile and execute this program.

Command

> scalac Demo.scala
> scala Demo

Output

Called method 'someMethod' with arguments 1, 2, 3

In the example, the class DynamicExample extends the Dynamic trait. It has dynamic method invocation. The applyDynamic method is used for method calls dynamically.

Advantages of Dynamic Invocation

There are various advantages of Dynamic invocation. It provides flexibility because method calls are resolved at runtime. You can integrate dynamic languages and frameworks. You can also reduce boilerplate code when working with repetitive method calls and when the method names are not known until runtime.

Dynamic Invocation with Reflection

You can achieve dynamic invocation using reflection too. It inspects and invokes methods on objects at runtime.

Syntax

The syntax of using reflection for dynamic invocation is -

import scala.reflect.runtime.universe._

def invokeMethod(obj: Any, methodName: String, args: Any*): Any = {
   val runtimeMirror = runtimeMirror(obj.getClass.getClassLoader)
   val instanceMirror = runtimeMirror.reflect(obj)
   val methodSymbol = runtimeMirror.reflectClass(instanceMirror.symbol.asClass).symbol.
   typeSignature.member(TermName(methodName)).asMethod
   instanceMirror.reflectMethod(methodSymbol)(args: _*)
}

Example

Consider the example of using reflection for dynamic invocation in Scala programming -

class Example {
   def greet(name: String): String = s"Hello, $name!"
}

object Demo {
   import scala.reflect.runtime.universe._

   def invokeMethod(obj: Any, methodName: String, args: Any*): Any = {
      val runtimeMirror = runtimeMirror(obj.getClass.getClassLoader)
      val instanceMirror = runtimeMirror.reflect(obj)
      val methodSymbol = runtimeMirror.reflectClass(instanceMirror.symbol.asClass).
         symbol.typeSignature.member(TermName(methodName)).asMethod
      instanceMirror.reflectMethod(methodSymbol)(args: _*)
   }

   def main(args: Array[String]): Unit = {
      val example = new Example
      println(invokeMethod(example, "greet", "Scala")) 
   }
}

Save the above program in Demo.scala. Use the following commands to compile and execute this program.

Command

> scalac Demo.scala
> scala Demo

Output

Hello, Scala!

In the example, the invokeMethod function uses reflection to dynamically. It invokes the greet method on Example object.

Dynamic Invocation in Scripting

Dynamic invocation is used in scripting environments where the method names and parameters are determined at runtime.

Syntax

The syntax of dynamic invocation in scripting contexts is similar to the previous examples. It uses either the Dynamic trait or reflection.

Example

Consider the example of using dynamic invocation in a scripting context in Scala programming -

import scala.language.dynamics

class Scriptable extends Dynamic {
   def applyDynamic(name: String)(args: Any*): String = {
      s"Executing script method '$name' with arguments ${args.mkString(", ")}"
   }
}

object Demo {
   def main(args: Array[String]): Unit = {
      val script = new Scriptable
      println(script.runScript("arg1", "arg2")) 
   }
}

Save the above program in Demo.scala. Use the following commands to compile and execute this program.

Command

> scalac Demo.scala
> scala Demo

Output

Executing script method 'runScript' with arguments arg1, arg2

In the example, the class Scriptable uses dynamic invocation. It simulates executing script methods with arbitrary names and arguments.

Dynamic Invocation with Dynamic Traits

Scala has dynamic traits to work with dynamic method invocation. You can extend these traits to create classes that support dynamic method calls.

Syntax

The syntax of using dynamic traits for dynamic invocation is -

import scala.language.dynamics

class DynamicExample extends Dynamic {
   def applyDynamic(name: String)(args: Any*): String = {
      s"Called method '$name' with arguments ${args.mkString(", ")}"
   }
}

Example

Consider the example of using dynamic traits for dynamic invocation in Scala programming -

import scala.language.dynamics

class DynamicExample extends Dynamic {
   def applyDynamic(name: String)(args: Any*): String = {
      s"Called method '$name' with arguments ${args.mkString(", ")}"
   }
}

object Demo {
   def main(args: Array[String]): Unit = {
      val example = new DynamicExample
      println(example.someMethod(1, 2, 3)) 
   }
}

Save the above program in Demo.scala. Use the following commands to compile and execute this program.

Command

> scalac Demo.scala
> scala Demo

Output

Called method 'someMethod' with arguments 1, 2, 3

In the example, the class DynamicExample extends Dynamic trait. So dynamic method invocation using the applyDynamic method.

Dynamic Invocation Summary

  • You can invoke methods on objects dynamically at runtime. So it provides flexibility and integration with dynamic languages and frameworks.
  • You can achieve dynamic invocation using Dynamic trait and reflection. So there can be method calls on objects whose types are not known until runtime.
  • Dynamic invocation enhances code flexibility, reduces boilerplate code, and integrates with dynamic languages and APIs.
  • Dynamic invocation can be used in various contexts, like scripting environments and dynamic trait implementations.
Advertisements