Is it possible to print the returned value of a function of different class in case of Anonymous object of scala - 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

Related

Mocking scala object called by under another object

I am trying to write unit test for a function under object1.
object Object1 {
def main(sysArgs: Array[String]): Unit = {
val inputDF: DataFrame = UtilObject.getInput()
}
}
object UtilObject {
def getInput(){
...
}
}
To write Unit test, I am using MockitoSugar.
"object1Main" should "should make correct calls" in {
val inputArgs = Array("abc")
val util = mock[UtilObject.type]
when(util.getInput().thenReturn(inputData))
Object1.main(inputArgs)
}
While running the test, it doesn't consider the util mock and just execute the getInput() function.
I think I am missing some sort of injection here. Any ideas?
Thanks in advance!
Mocking Scala objects should be impossible conceptually speaking. An object in Scala is a pure singleton. That means there can only be one member of that type at any time.
mockito-scala can mock Scala objects via reflection. I'll use a result type of String, instead of a DataFrame, but the idea is the same:
object UtilObject {
def getInput(): String = {
// ...
"done"
}
}
object Object1 {
def main(sysArgs: Array[String]): String = {
val inputDF: String = UtilObject.getInput()
inputDF
}
}
// in test file:
"object1Main" should {
"should make correct calls" in {
val inputArgs = Array("abc")
withObjectMocked[UtilObject.type] {
UtilObject.getInput() returns "mocked!"
Object1.main(inputArgs) shouldBe "mocked!"
}
Object1.main(inputArgs) shouldBe "done"
}
}
This mocks the singleton's method only inside the block of withObjectMocked.
Usually such powerful techniques often tend to be overused or misused, so I don't generally recommend them, unless the design cannot be refactored.
Luckily, yours can: the easiest way is to use Dependency Injection with a class or a function. For DI with a class you require to convert the object being mocked into a class:
class UtilObject {
def getInput(): String = {
// ...
"done"
}
}
object Object1 {
def main(sysArgs: Array[String], ut: UtilObject): String = {
val inputDF: String = ut.getInput()
inputDF
}
}
// in test file:
"object1Main" should {
"should make correct calls" in {
val inputArgs = Array("abc")
val util = mock[UtilObject]
when(util.getInput()).thenReturn("mocked!")
Object1.main(inputArgs, util) shouldBe "mocked!"
}
}
For DI with a function you need to lift the method you want to mock into a function:
object UtilObject {
def getInput(): String = {
// ...
"done"
}
}
object Object1 {
def main(sysArgs: Array[String], f: () => String = UtilObject.getInput): String = {
val inputDF: String = f()
inputDF
}
}
// in test file:
"object1Main" should {
"should make correct calls" in {
val inputArgs = Array("abc")
val f = mock[() => String]
when(f()).thenReturn("mocked!")
Object1.main(inputArgs, f) shouldBe "mocked!"
}
}
Since the function takes no arguments, you can convert it into a by-name parameter. I'll leave that to you.
Lastly, another way is to create a trait with the method you want to mock and extend that with the object. But now Object1 requires being a class and have a reference to the object being mocked:
object UtilObject extends Utils {
def getInput(): String = {
// ...
"done"
}
}
trait Utils {
def getInput(): String
}
class Object1 {
val uo: Utils = UtilObject
def main(sysArgs: Array[String]): String = {
val inputDF: String = uo.getInput()
inputDF
}
}
// in test file:
"object1Main" should {
"should make correct calls" in {
val classUnderTest = new Object1 {
override val uo = mock[Utils]
}
val inputArgs = Array("abc")
when(classUnderTest.uo.getInput()).thenReturn("mocked!")
classUnderTest.main(inputArgs) shouldBe "mocked!"
}
}
As you can see, there are a few ways to go. Neither is inherently wrong. It mostly depends on your requirements(e.g. you can't afford adding a dependency just for one UT), needs(e.g. does the object I am testing really needs to be an object or can I make it a class?), guidelines (e.g. your team decided to avoid using powerful testing frameworks that rely on reflection and use DI as much as possible instead) and personal preferences.

Scala Internal Class Typing - Type Mismatch Error

I am experiencing a very strange typing error when running the below code.
The goal of this code is to have a class that can combine other instances of this class with itself, producing the updated instance. (Perhaps I should prefer immutability and return copies, but that's another discussion).
IntelliJ does not complain until I attempt to run the code, then it crashes with
type mismatch found: mic.MyInternalClass
required: MyClass.this.MyInternalClass this.myVar =
this.myVar.combine(mic.myVar)"
IntelliJ Error Message
class MyClass(s: String) {
var myVar: MyInternalClass = new MyInternalClass(s)
def combine(mic: MyClass): MyClass = {
this.myVar = this.myVar.combine(mic.myVar)
this
}
class MyInternalClass(s: String) {
var myInternalVar: String = s
def combine(mic: MyInternalClass): MyInternalClass = {
this.myInternalVar += mic.myInternalVar
this
}
}
}
object App {
def main(args : Array[String]) {
var mc1: MyClass = new MyClass("dog")
var mc2: MyClass = new MyClass("cat")
mc1.combine(mc2)
println(mc1.myVar.myInternalVar)
println(mc2.myVar.myInternalVar)
}
}
Each instance's MyInternalClass is considered a separate type in Scala, so you can't mix this's and mic's MyInternalClass. If that's not what you want, instead of using MyClass#MyInternalClass everywhere it's better to move MyInternalClass declaration to the companion object:
// otherwise you'll need to write MyClass.MyInternalClass explicitly even inside MyClass
import MyClass.MyInternalClass
class MyClass(s: String) {
var myVar: MyInternalClass = new MyInternalClass(s)
def combine(mic: MyClass): MyClass = {
this.myVar = this.myVar.combine(mic.myVar)
this
}
}
object MyClass {
class MyInternalClass(s: String) {
var myInternalVar: String = s
def combine(mic: MyInternalClass): MyInternalClass = {
this.myInternalVar += mic.myInternalVar
this
}
}
}
I just found this link: Referring to the type of an inner class in Scala
It looks like the inner class method needs a special type like so:
def combine(mic: MyClass#MyInternalClass): MyInternalClass = {
Still learning the nuances of why this is the case.

Dynamically access methods from scala object

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 ...

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 closure context

I am not a Groovy expert, but I did read the book "Groovy in Action". In Groovy, each closure comes with a "context", where the items inside the closure can get access to pseudo-variables like "this", "owner", and "delegate", that let the items know who called the closure. This allows one to write DSLs like this (from Groovy in Action):
swing = new SwingBuilder()
frame = swing.frame(title:'Demo') {
menuBar {
menu('File') {
menuItem 'New'
menuItem 'Open'
}
}
panel {
// ...
}
}
Note that 'menuBar' "knows" that it belongs to 'frame' because it can get context information about the owner and delegate of the closure.
Is this possible to do in Scala? If so, how?
One way is to use a scala.util.DynamicVariable to track the context. Something like the SwingBuilder could be implemented as
import scala.util.DynamicVariable
import javax.swing._
object SwingBuilder {
case class Context(frame: Option[JFrame], parent: Option[JComponent])
}
class SwingBuilder {
import SwingBuilder._
val context = new DynamicVariable[Context](Context(None,None))
def frame(title: String)(f: =>Unit) = {
val res = new JFrame(title)
res.add(new JPanel())
context.withValue(Context(Some(res),context.value.parent)){f;res}
}
def menuBar(f: =>Unit) = {
val mb = new JMenuBar()
context.value.frame.foreach(_.setJMenuBar(mb))
context.withValue(Context(context.value.frame,Some(mb))){f;mb}
}
def menu(title: String)(f: =>Unit) = {
val m = new JMenu(title)
context.value.parent.foreach(_.asInstanceOf[JMenuBar].add(m))
context.withValue(Context(context.value.frame,Some(m))){f;m}
}
def menuItem(title: String) = {
val mi = new JMenuItem(title)
context.value.parent.foreach(_.asInstanceOf[JMenu].add(mi))
}
}
object Test {
def main(args: Array[String]) {
val builder = new SwingBuilder()
import builder._
val f = frame("Demo") {
val mb = menuBar {
menu("File") {
menuItem("New")
menuItem("Open")
}
}
}
f.setVisible(true)
}
}