Dynamically access methods from scala object - scala

In Scala, what's the best way to dynamically call an object and invoke a method using reflection? The method corresponding to the object is to be called but the object name is known dynamically.
I was able to instantiate a scala class dynamically from this SO question however I need to do the same thing for an object.
Here is a sample code for some clarity:
class CC {
def CC () = {
}
}
object CC {
def getC(name : String) : CC = {
return new CC();
}
}
}
class CD {
def CD () = {
}
}
object CD {
def getC(name : String) : CC = {
return new CD();
}
}
}
Now I've a base class, which needs to call the getC method but the corresponding object is know dynamically. So how does one achieve the same?
Also the base class and my doubt is in the comments of the class.
class Base {
def Base() = {
}
def createClass(name : String) = {
// need to call the method corresponding to the object depending
// on the string.
//e.g.: if name = "C" call CC.getC("abcd")
// if name = "D" call CD.getC("abcd")
}
}

You could still use scala runtime reflection:
import scala.reflect.runtime.{universe => ru}
val m = ru.runtimeMirror(getClass.getClassLoader)
val ccr = m.staticModule("my.package.name.ObjName") // e.g. "CC" or "CD"
type GetC = {
def getC(name:String): CC
}
val cco = m.reflectModule(ccr).instance.asInstanceOf[GetC]
now you could use it as cco.getC ...

Related

Scala mocking the behaviour

When I mock the particular object method is executing the actual behavior.
The expected output should be 10since I mocked the Calculate.add and returning the result as 10
trait Base {
def add (parm1:Int, parm2:Int): Int
def fetc ():Any
def compute(): Any
}
object Calculate extends Base {
def add(parm1:Int, parm2:Int):Int = {
fetc()
compute
}
def fetc ():Any = {
// Making some api1 call
}
def compute ():Any = {
// Making some api2 call
}
}
object Engine {
def execute():any{
Calculate.add(10, 20)
}
}
Test
class TestEngine extends MockFactory {
it should "compute" in {
val res1:Int = 10
val calculate: Base = stub[Base]
val data = (calculate.add _).when(10, 20).returns(res1);
Engine.execute() // ExpectedOutput should be 10(res1),Since the I mocked the add method and returning the 10 value. Should not call the Calculate object fetch, compute behaviour.
}
}
Though Calculate is mocked & add method has been stubbed, still the actual functionality of add will be executed, since in Engine.execute method Calculate object reference is used to access the add method also Calculate is itself an object, thus the actual code will be executed.
object Engine {
def execute():any{
Calculate.add(10, 20)
}
}
Simple solution to mocked calculate in Engine.execute could be instead of using Calculate object passed a base variable as method parameter.
object Engine {
def execute(base: Base): Int = {
base.add(10, 20)
}
}
class TestEngine extends MockFactory {
it should "compute" in {
val res1: Int = 10
val calculate: Base = stub[Base]
val data = (calculate.add _).when(10, 20).returns(res1);
//mocked_calculate
Engine.execute(mocked_calculate)
}
}

Is it possible to print the returned value of a function of different class in case of Anonymous object of scala

I am new to Scala, trying to understand the syntactic behaviors of Scala. I will be really appreciated if anybody help me. Thanks
With Anonymous Object: Here in this scenario if I want to print the value of resinside the main function body then what logic I need to apply?
package oops
object AnonymousObject
{
def main(args:Array[String]):Unit =
{
new student().detail(5,9) // Line 1
}
}
class student
{
def detail(x:Int, y:Int):Int =
{
val res = x*y
println(res)
}
}
Without Anonymous Object:
For more information, in this scenario given below, there has no problem to achieve it because of var s
class Student
{
var id:Int = 0; // All fields must be initialized
var name:String = null;
}
object MainObject
{
def main(args:Array[String])
{
var s = new Student() // Creating an object
println(s.id+" "+s.name);
}
}
An object which has no reference name. So simply you can print like this way inside the main
object AnonymousObject
{
def main(args:Array[String]):Unit =
{
val res = new student().detail(5,9)
println(res)
}
}
class student
{
def detail(x:Int, y:Int):Int =
{
x*y
}
}
Output: 45

Class A cannot be cast to Class A after dynamic loading

Let's say I have:
object GLOBAL_OBJECT{
var str = ""
}
class A(_str: String){
GLOBAL_OBJECT.str = _str
}
and I would like to create 2 copies of GLOBAL_OBJECT (for tests), so I am using different classloader to create obj2:
val obj1 = new A("1")
val class_loader = new CustomClassLoader()
val clazz = class_loader.loadClass("my.packagename.A")
val obj2 = clazz.getDeclaredConstructor(classOf[String]).newInstance("2")
println("obj1.getSecret() == " + obj1.getSecret()) // Expected: 1
println("obj2.getSecret() == " + obj2.asInstanceOf[A].getSecret()) // Expected: 2
which results following error:
my.packagename.A cannot be cast to my.packagename.A.
IntelliJ Idea seems to do it correctly, I can run obj2.asInstanceOf[A].getSecret() in "expression" window during debug process without errors.
PS. I have seen similar questions, but I could not find any not regarding loading class from .jarfile.
You're not going to be able to get around Java's class casting, which requires strict typing, within the same ClassLoader. Same with traits/interfaces.
However, Scala comes to the rescue with structural typing (a.k.a. Duck Typing, as in "it quacks like a duck.") Instead of casting it to type A, cast it such that it has the method you want.
Here's an example of a function which uses structural typing:
def printSecret(name : String, secretive : { def getSecret : String } ) {
println(name+".getSecret = "+secretive.getSecret)
}
And here's sample usage:
printSecret("obj1", obj1) // Expected: 1
printSecret("obj2", obj2.asInstanceOf[ {def getSecret : String} ]) // Expected: 2
You could, of course, just call
println("secret: "+ obj2.asInstanceOf[ {def getSecret : String} ].getSecret
Here's full sample code that I wrote and tested.
Main code:
object TestBootstrap {
def createClassLoader() = new URLClassLoader(Array(new URL("file:///tmp/theTestCode.jar")))
}
trait TestRunner {
def runTest()
}
object RunTest extends App {
val testRunner = TestBootstrap.createClassLoader()
.loadClass("my.sample.TestCodeNotInMainClassLoader")
.newInstance()
.asInstanceOf[TestRunner]
testRunner.runTest()
}
In the separate JAR file:
object GLOBAL_OBJECT {
var str = ""
}
class A(_str: String) {
println("A classloader: "+getClass.getClassLoader)
println("GLOBAL classloader: "+GLOBAL_OBJECT.getClass.getClassLoader)
GLOBAL_OBJECT.str = _str
def getSecret : String = GLOBAL_OBJECT.str
}
class TestCodeNotInMainClassLoader extends TestRunner {
def runTest() {
println("Classloader for runTest: " + this.getClass.getClassLoader)
val obj1 = new A("1")
val classLoader1 = TestBootstrap.createClassLoader()
val clazz = classLoader1.loadClass("com.vocalabs.A")
val obj2 = clazz.getDeclaredConstructor(classOf[String]).newInstance("2")
def printSecret(name : String, secretive : { def getSecret : String } ) {
println(name+".getSecret = "+secretive.getSecret)
}
printSecret("obj1", obj1) // Expected: 1
printSecret("obj2", obj2.asInstanceOf[ {def getSecret : String} ]) // Expected: 2
}
}
Structural typing can be used for more than one method, the methods are separated with semicolons. So essentially you create an interface for A with all the methods you intend to test. For example:
type UnderTest = { def getSecret : String ; def myOtherMethod() : Unit }
One workaround to actually run some method from dynamically delivered object instead of casting it is to use reflection in order to extract particular method, from new class and then invoke it on our new object instance:
val m2: Method = obj2.getClass.getMethod("getSecret")
m2.invoke(obj2)
The class file that contains obj2.asInstanceOf[A].getSecret() should be reloaded by CustomClassLoader, too.
And you must not use any class that references to A unless you reload the class by the same class loader that reloads A.

Scala: Can I reproduce anonymous class creation with a factory method?

As far as I understand it, Scala creates an anonymous class if I create a class using the new keyword and follow the class name with a constructor:
class MyClass {
def doStuff() {
// ...
}
}
val mc = new MyClass {
doStuff()
}
The nice thing being that all the code in the constructor is in the scope of the new object.
Is there a way I can reproduce this syntax where the class is created by a factory method rather than the new keyword? i.e. make the following code work:
val mf = new MyFactory
val mc = mf.MyClass {
doStuff()
}
I can't find a way to do it but Scala has so much to it that this might be pretty easy!
Using an import as suggested by #Ricky below I can get:
val mf = MyFactory;
val mc = mf.MyClass
{
import mc._
doStuff()
}
(Where the blank line before the block is needed) but that code block is not a constructor.
You can do this, but you still have to keep the new keyword, and create the nested class as a path-dependent type:
class Bippy(x: Int) {
class Bop {
def getIt = x
}
}
val bip = new Bippy(7)
val bop = new bip.Bop
bop.getIt // yields 7
val bop2 = new bip.Bop{ override def getIt = 42 }
bop2.getIt // yields 42
I don't think it's possible. However, a common pattern is to add a parameter to factory methods which takes a function modifying the created object:
trait MyClass {
var name = ""
def doStuff():Unit
}
class Foo extends MyClass {
def doStuff() { println("FOO: " + name) }
}
trait MyClassFactory {
def make: MyClass
def apply( body: MyClass => Unit ) = {
val mc = make
body(mc)
mc
}
}
object FooFactory extends MyClassFactory {
def make = new Foo
}
You can then create and modify instance with a syntax close to your example:
val foo = FooFactory { f=>
f.name = "Joe"
f.doStuff
}
It sounds like you're just looking to mix in a trait. Instead of calling myFactoryMethod(classOf[Foo]] which ideally would do (if Scala permitted it):
new T {
override def toString = "My implementation here."
}
you can instead write
trait MyImplementation {
override def toString = "My implementation here."
}
new Foo with MyImplementation
However, if you are just looking to get the members of the new object accessible without qualification, remember you can import from any stable identifier:
val foo = new Bar
import foo._
println(baz) //where baz is a member of foo.

Scala passing a reference to this class

I have a class, with multiple methods and members. When I create an instance of this class, I create an instance of another class within the first class. Some of the methods in this second class require to know which instance of the first class is running. Currently, I am trying to pass "this" into the argument that accepts type firstClass. What am I doing wrong? Again, I simply want the second class instance knowing what first class instance it belongs to so that it can call public methods and members from it.
EDIT: Code example:
def main(args:Array[String]) : Unit = {
val objectOne = new classOne
}
class classOne {
val mutableBuffer = mutable.Buffer[String]
val objectTwo = new classTwo
objectTwo.doThis(this)
}
class classTwo {
def doThis (exA:classOne) = {
exA.mutableBuffer += "Adding text to a Buffer in object One"
}
}
Self-typing is often the cleanest solution here
class Bippy {
outer =>
...
class Bop {
def demoMethod() = println(outer)
}
...
}
UPDATE
The example code changes everything, this clearly isn't about inner classes. I believe your problem is in this line:
val mutableBuffer = mutable.Buffer[String]
It isn't doing what you think it's doing, mutableBuffer is now pointing to the mutable.Buffer singleton, it isn't actually an instance of a Buffer
Instead, try one of these two:
val mutableBuffer = mutable.Buffer[String]()
//or
val mutableBuffer = mutable.Buffer.empty[String]
You should also stick to the convention of starting class/singleton/type names with an uppercase letter, turning your example code into:
import collection.mutable.Buffer
def main(args:Array[String]) : Unit = {
val one = new ClassOne()
}
class ClassOne {
val mutableBuffer = Buffer.empty[String]
val two = new ClassTwo()
two.doThis(this)
}
class ClassTwo {
def doThis(one: ClassOne) = {
one.mutableBuffer += "Adding text to a Buffer in object One"
}
}
I had to make some superficial changes to your example code in order to make it run:
import scala.collection.mutable
class classOne {
val mutableBuffer : mutable.Buffer[String] = new mutable.ArrayBuffer[String]
val objectTwo = new classTwo
objectTwo.doThis(this)
}
class classTwo {
def doThis (exA : classOne) = {
exA.mutableBuffer += "Adding text to a Buffer in object One"
}
}
val objectOne = new classOne
println(objectOne.mutableBuffer(0))
But it works as expected. The classTwo object is able to modify the classOne object. Do you need something beyond this functionality?