DRY up boilerplate in object/class default constructor - scala

I have something like this:
abstract class RunnerBase { def printErrorAndBreak = ... }
object Runner1 extends RunnerBase {
breakable {
doSomething
if (cond1) printErrorAndBreak(...)
}
}
object Runner2 extends RunnerBase {
breakable {
if (cond1) printErrorAndBreak(...)
something else
}
}
I'd like to move the breakable { ... } part into RunnerBase so that Runner1 and Runner2 looked like this instead:
object Runner1 extends RunnerBase {
doSomething
if (cond1) printErrorAndBreak(...)
}
object Runner2 extends RunnerBase {
if (cond1) printErrorAndBreak(...)
something else
}
Is this even possible? Or is my only way to wrap the subobject logic in, say, a run method?
UPDATE: Based on the accepted answer (and regardless of the comments), for the sake of robustness and simplicity, I've decided to go with this:
class RunnerBase { def run = breakable _ }
class Runner1 { run { doSmth; if (?) printErrorAndBreak } }
class Runner2 { run { doSmth; if (?) printErrorAndBreak } }
Not perfect because there's still the run { ... } repetition, but at least breakable and break are encapsulated in RunnerBase.

How about DelayedInit?
import scala.util.control.Breaks._
trait BreakInit extends DelayedInit {
def delayedInit(body: => Unit) {
breakable {body}
}
}
class MyClass extends BreakInit {
println("Hello World")
break()
println("Error - should not be reachable")
}
val a = new MyClass
In this case, we've created a trait BreakInit that inherits from DelayedInit, which overrides the delayedInit method to call the constructor within a breakable block. MyClass's constructor is then rolled up into a function, and passed to the delayedInit method. As #som-snytt points out, the DelayedInit magic only affects class constructors, not trait constructors.
However, I'd advise a note of caution when using DelayedInit. It involves some reasonably deep compiler magic, and magic always comes with a price. Personally, I'd tend to prefer your original approach, as there's less magic involved.

Related

Mockito-Mock functions within scala object for unit testing

I have a few functions within a scala object. The functions internally call other functions of the same object.
object A {
def method1:Unit= {
spark=CreateSparkSession.create()
Method2(spark,dbnm)
}
def Method2(spark:Sparksession, dbnm:String):Unit= {
//some implementation
}
}
How can I write Unit testcase for Method1 without actually invoking method2.
CreateSparksession is another object with create method that returns sparksession.
You cannot mock methods in an object. And you should not mock methods in class that you are testing (if it looks like you need to, it is a definite symptom of violating the single responsibility principle).
What you can do is something like this:
trait Api1 {
def method1(
...
): Unit // NB: also, should not really return a Unit: how are you going to test this???
}
trait Api2 {
def method2(...): Unit // See above
}
class Impl2 extends Api2 {
def method2(...) = // Do stuff
}
class Impl1(val api2: Api2) extends Api1 {
def method1(...) = { ... ; api2.method2(); ... }
}
// You should not really need this, but, you can have it if you want
object A extends Impl1(new Impl2)
So, now testing this code is trivial:
describe("Impl2") {
it ("does nothing") {
new Impl2().method2("foo")
// Nothing happens
// this is what I meant: how do you know it worked?
}
}
describe("Impl1") {
it ("does nothinig") {
val a2 = mock[Api2]
doNothing when a2 method2(any)
val fixture = new Impl1(a2)
fixture.method1()
// Again, nothing happens!
verify(a2).nothing("foo")
}

Invoking scala classes which extends traits during runtime

I am relatively new to scala so please bear me if I asked silly questions.
I have a requirement where I need to invoke a method run time.
I have a trait which is being extended by two classes
trait Animal {
def walk():DataFrame
}
This is extended by two classes.
class Dog(sparkSession: SparkSession) extends Animal {
def walk():DataFrame = {
.............
}
}
class Cat(sparkSession: SparkSession) extends Animal {
def walk():DataFrame = {
.............
}
}
Now from a config file I will get a list of these class names
Lets say like this
val animals = ["com.xy.Dog","com.xy.Cat"]
I need to invoke these classes and execute walk methods.
Can I do something like this?
animals.forEach{ animalString =>
val animalObject = Class.forName(animalString ).newInstance().asInstanceOf(Animal)
animalObject.walk
}
There are a few issues, let's take them one by one:
To build a list in scala you need to do:
val animals = List("com.xy.Dog", "com.xy.Cat")
The forEach method is actually foreach, so there's a small typo. Finally, when you call the newInstance you should get the appropriate constructor before that, otherwise it will use the default one.
animals.foreach { animalString =>
val animalObject = Class.forName(animalString)
.getConstructor(classOf[DataFrame]) // Get the constructor for a DataFrame argument
.newInstance(dataframe) // Pass the dataframe instance
.asInstanceOf[Animal]
animalObject.walk
}
I've made a couple of small changes to the code for you to see it working. You can run the app to see the output:
class Dog extends Animal {
def walk(): Unit = { println("I'm a dog.") }
}
class Cat extends Animal {
def walk(): Unit = { println("I'm a cat.") }
}
object AnimalTest extends App {
val animals = List("com.xy.Dog", "com.xy.Cat")
animals.foreach { animalString =>
val animalObject = Class.forName(animalString)
.newInstance()
.asInstanceOf[Animal]
animalObject.walk
}
}
Note that I've removed the constructor arguments here to easily build instances. The rest is about the same. I hope this helps you.

Scala: reconfigure trait using CLI parameters

I have a Scala application, where pretty much every object extends a specific trait, which holds all the main functions and variables used by pretty much the entire system.
I want to add a --testing flag to my app's command line variables, which will shift the the results of some of the functions in the trait.
Putting it simply, I'd like the variable accepted in the main to have an affect that alters something in the trait before it is extended by the objects - without sending it explicitly to all objects.
Any ideas how that can be performed?
I doubt you really want to dynamically modify a trait, and I am not sure if it possible that all your classes inheriting that trait would be affected. I don't know enough about the compiler and byte code.
A way to accomplish something similar would be to have your trait take a parameter, and make your trait act conditionally on the parameter.
trait Foo {
val testing: Boolean
def fn1(): Unit = {
if (testing) {
println("testing")
} else {
println("production")
}
}
}
class Bar(val testing: Boolean) extends Foo {
def fn2(): Unit = {
fn1()
}
}
new Bar(true).fn2()
new Bar(false).fn2()
Your question is broad and this is just my 5 cents.
Update
trait Foo {
def fn1(): Unit = {
if (Foo.testing) {
println("testing")
} else {
println("production")
}
}
}
object Foo {
var testing: Boolean = false
}
class Bar extends Foo {
def fn2(): Unit = {
fn1()
}
}
object SOApp extends App {
new Bar().fn2()
Foo.testing = true
new Bar().fn2()
}
Consider passing the 'testing' flag to the trait's initializer block like this:
trait MyTrait {
var testMode: Boolean = _
def doSomething(): Unit = {
if (testMode)
println("In Test Mode")
else
println("In Standard Mode")
}
}
// IMPORTANT: Your best bet would be to create some Config object
// that is loaded and initialized in a main method.
// Define test-specific Config class:
case class Config(testMode: Boolean) {
def isTestMode: Boolean = this.testMode
}
// Instantiate in main method:
val config = new Config(true)
// Later, extend the trait:
class MyObj extends MyTrait { testMode = config.isTestMode() }
// Then just invoke
new MyObject().doSomething()

Call function automatically without an explicit call in every implementation of another function in subclasses

I've got something similar to the code below. I would like to add a bit of code to the end of each bar function e.g., foo. I think I might need to use type classes and implicit or perhaps abstract override. Any thoughts? Thanks in advance.
trait A {
def foo = { //do something }
}
case class B() extends A {
def bar = {
// do other stuff
// automatically call foo
}
}
case class C() extends A {
def bar = {
// do different stuff
// automatically call foo
}
}
You can't make it call automatically. How should the compiler know what to call? Magic?
You can impl. a default bar and call super.bar
def bar = foo
....
def bar = {
//do stuff
super.bar
}
but unless bar calls multiple methods, this is useless.
It sounds like you're looking for something like after in aspect-oriented programming. The easiest way to do this in any OO language is to follow the rule that public methods are always final. This separates the interface between the base and derived classes from the interface between the base class and its callers. That is:
trait A {
private def foo = { }
protected def on_bar = { }
final def bar = { on_bar; foo; }
};
case class B() extends A {
def on_bar = { do_other_stuff; }
}
It's not completely clear what's you're up to, but it sounds similar to the stackable trait pattern. Have a look and tell if it's something that you want, in that case I can provide more info on that, even though that article is pretty self-explanatory.

Scala abstract class method that returns a new corresponding class child object

I have the following class in my mind:
abstract class MyClass (data: MyData) {
def update(): MyClass = {
new MyClass(process())
}
def process(): MyData = {
...
}
}
However, abstract classes cannot be instantiated so the line new MyClass(process()) is an error. My question is - is there any way to tell the compiler that in case of each of the child classes of MyClass I want to create an object of exactly that child class? It seems an overkill to write this method awhole in all child classes. Playing with type parameters of the class or method I could not acheive that myself.
How about something like this? MyClass is parametrized with the concrete type. Of course, all concrete classes have to implement a method that actually returns a new instance of Self.
trait MyClass[+Self <: MyClass[Self]] {
def update(): Self = {
makeNew(process())
}
def process(): MyData = {
// ...
}
protected def makeNew(data: MyData): Self
}
class Concrete0 extends MyClass[Concrete0] {
protected def makeNew(data: MyData) = new Concrete0
}
class RefinedConcrete0 extends Concrete0 with MyClass[RefinedConcrete0] {
override protected def makeNew(data: MyData) = new RefinedConcrete0
}
Credit: IttayD’s second update to his answer to this question.
To completly avoid implementing almost identical method in all subclasses you would need to use reflection. I guess that would be your last resort if you have chosen Scala.
So here is how to minimize the repetitive code:
// additional parameter: a factory function
abstract class MyClass(data: MyData, makeNew: MyData => MyClass) {
def update(): MyClass = {
makeNew(process())
}
def process(): MyData = {
...
}
}
class Concrete(data: MyData) extends MyClass(data, new Concrete(_))
This way you repeat only the shortest fragment required to instantiate the subclass.