Scala constructor overloading parameter is not taking effect - scala

I'm trying to understand what's wrong with the way I'm implementing constructor overloading. I want to add a constructor that accepts an argument count, in a class that has a member with the same name.
The idea is to have count calculated off of one of the default constructor parameters, unless it is passed through the overload constructor. I show the code later.
To convince myself this can work, I constructed a quick and simple test:
import org.scalatest.FunSuite
class ConstructorOverloadTest extends FunSuite {
test("Overload parameter shadows class member") {
val actual = new TestME(200).length
200 === actual
1 !== actual
}
class TestME(name:String) {
val length = name.length
def this(length:Int) = {
this("*")
}
}
}
The test passes as expected. Which leads me to understand that the overload constructor parameter length shadows/replaces the class member length.
But when I do the same in another class, the class member is not shadowed/replaced.
class MyClass(input1: Array[Float], input2: Array[Byte], input3: Array[Float]) {
val count = input2.length
val index = doSomething()
def this(count: Int) = {
this(Array(), Array(), Array())
}
def printCount() = {
if (this.count == 0)
println("ZERO")
else
println("OTHER")
}
}
When I use this class as follows
val myInstance = new MyClass(200)
myInstance.printCount()
I expect it to print OTHER to the screen. Instead, it prints ZERO.
Why?

There appears to be something wrong with your test. new TestME(200).length returns 1, indicating that the constructor param does not in fact override length.
class TestME(name:String) {
val length = name.length
def this(length:Int) = {
this("*")
}
}
println(new TestME(200).length)
1
Per summerbulb's comments:
The test's assertions should be wrapped in assert:
// Closer to correct...
assert(200 === actual)
assert(1 !== actual)
Actual and expected values should be passed in that order:
// Correct!
assert(actual === 200)
assert(actual !== 1)

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)
}
}

Scala Reflection Conundrum: Can you explain these weird results?

I wrote some Scala code, using reflection, that returns all vals in an object that are of a certain type. Below are three versions of this code. One of them works but is ugly. Two attempts to improve it don't work, in very different ways. Can you explain why?
First, the code:
import scala.reflect.runtime._
import scala.util.Try
trait ScopeBase[T] {
// this version tries to generalize the type. The only difference
// from the working version is [T] instead of [String]
def enumerateBase[S: universe.TypeTag]: Seq[T] = {
val mirror = currentMirror.reflect(this)
universe.typeOf[S].decls.map {
decl => Try(mirror.reflectField(decl.asMethod).get.asInstanceOf[T])
}.filter(_.isSuccess).map(_.get).filter(_ != null).toSeq
}
}
trait ScopeString extends ScopeBase[String] {
// This version works but requires passing the val type
// (String, in this example) explicitly. I don't want to
// duplicate the code for different val types.
def enumerate[S: universe.TypeTag]: Seq[String] = {
val mirror = currentMirror.reflect(this)
universe.typeOf[S].decls.map {
decl => Try(mirror.reflectField(decl.asMethod).get.asInstanceOf[String])
}.filter(_.isSuccess).map(_.get).filter(_ != null).toSeq
}
// This version tries to avoid passing the object's type
// as the [S] type parameter. After all, the method is called
// on the object itself; so why pass the type?
def enumerateThis: Seq[String] = {
val mirror = currentMirror.reflect(this)
universe.typeOf[this.type].decls.map {
decl => Try(mirror.reflectField(decl.asMethod).get.asInstanceOf[String])
}.filter(_.isSuccess).map(_.get).filter(_ != null).toSeq
}
}
// The working example
object Test1 extends ScopeString {
val IntField: Int = 13
val StringField: String = "test"
lazy val fields = enumerate[Test1.type]
}
// This shows how the attempt to generalize the type doesn't work
object Test2 extends ScopeString {
val IntField: Int = 13
val StringField: String = "test"
lazy val fields = enumerateBase[Test2.type]
}
// This shows how the attempt to drop the object's type doesn't work
object Test3 extends ScopeString {
val IntField: Int = 13
val StringField: String = "test"
lazy val fields = enumerateThis
}
val test1 = Test1.fields // List(test)
val test2 = Test2.fields // List(13, test)
val test3 = Test3.fields // List()
The "enumerate" method does work. However, as you can see from the Test1 example, it requires passing the object's own type (Test1.type) as a parameter, which should not have been necessary. The "enumerateThis" method tries to avoid that but fails, producing an empty list. The "enumerateBase" method attempts to generalize the "enumerate" code by passing the val type as a parameter. But it fails, too, producing the list of all vals, not just those of a certain type.
Any idea what's going on?
Your problem in your generic implementation is the loss of the type information of T. Also, don't use exceptions as your primary method of control logic (it's very slow!). Here's a working version of your base.
abstract class ScopeBase[T : universe.TypeTag, S <: ScopeBase[T, S] : universe.TypeTag : scala.reflect.ClassTag] {
self: S =>
def enumerateBase: Seq[T] = {
val mirror = currentMirror.reflect(this)
universe.typeOf[S].baseClasses.map(_.asType.toType).flatMap(
_.decls
.filter(_.typeSignature.resultType <:< universe.typeOf[T])
.filter(_.isMethod)
.map(_.asMethod)
.filter(_.isAccessor)
.map(decl => mirror.reflectMethod(decl).apply().asInstanceOf[T])
.filter(_ != null)
).toSeq
}
}
trait Inherit {
val StringField2: String = "test2"
}
class Test1 extends ScopeBase[String, Test1] with Inherit {
val IntField: Int = 13
val StringField: String = "test"
lazy val fields = enumerateBase
}
object Test extends App {
println(new Test1().fields)
}
Instead of getting the type from universe.typeOf you can use the runtime class currentMirror.classSymbol(getClass).toType, below is an example that works:
def enumerateThis: Seq[String] = {
val mirror = currentMirror.reflect(this)
currentMirror.classSymbol(getClass).toType.decls.map {
decl => Try(mirror.reflectField(decl.asMethod).get.asInstanceOf[String])
}.filter(_.isSuccess).map(_.get).filter(_ != null).toSeq
}
//prints List(test)
With everyone's help, here's the final version that works:
import scala.reflect.runtime.{currentMirror, universe}
abstract class ScopeBase[T: universe.TypeTag] {
lazy val enumerate: Seq[T] = {
val mirror = currentMirror.reflect(this)
currentMirror.classSymbol(getClass).baseClasses.map(_.asType.toType).flatMap {
_.decls
.filter(_.typeSignature.resultType <:< universe.typeOf[T])
.filter(_.isMethod)
.map(_.asMethod)
.filterNot(_.isConstructor)
.filter(_.paramLists.size == 0)
.map(decl => mirror.reflectField(decl.asMethod).get.asInstanceOf[T])
.filter(_ != null).toSeq
}
}
}
trait FieldScope extends ScopeBase[Field[_]]
trait DbFieldScope extends ScopeBase[DbField[_, _]] {
// etc....
}
As you see from the last few lines, my use cases are limited to scope objects for specific field types. This is why I want to parameterize the scope container. If I wanted to enumerate the fields of multiple types in a single scope container, then I would have parameterized the enumerate method.

Trying to implement a Circular Enumeration in Scala

Below is the trait that I would like to use
trait CircularEnumeration extends Enumeration {
class CircularVal extends Val {
def next(): Value = {
apply((id + 1) % values.size)
}
}
protected override final def Value: CircularVal = new CircularVal;
///////////////////////////////////////////////////////////////////////////
def nextValue(value: Value) = {
//first way
val nextIndex = values.toSeq.indexOf(value) + 1;
val value_nomath = if (nextIndex >= values.size) {
values.toSeq(0);
}
else {
values.toSeq(nextIndex);
}
//second way
val value_withmath = this((value.id + 1) % values.size);
assert(value_nomath == value_withmath);
value_withmath;
}
}
You can see that I already have tried two ways, and both have failed.
In the first the usage would be something like this:
MyEnumeration(index).next
and this would return me the next value of this enumeration
In the second the usage would be like that:
MyEnumeration.nextValue(MyEnumeration(index))
and once again this would return the next value
but in both occasions I have issues of which type is which. Because inside the trait the Value is actually CircularEnumeration.Value while inside the class which has this trait tha Value is MyEnumeration.Value
Any ideas?
I believe I can get it to work with the following changes - modify the return type of nextValue:
def nextValue(value: Value): CircularEnumeration.this.Value = {
and the last line (returned value) to:
value_withmath.asInstanceOf[CircularEnumeration.this.Value]
Then, defining MyEnumeration as:
scala> object MyEnumeration extends CircularEnumeration {
| type MyEnumeration = Value
| val Zero, One, Two, Three, Four = Value
| }
defined module MyEnumeration
we get:
scala> MyEnumeration.nextValue(MyEnumeration(3))
res0: MyEnumeration.Value = Four
scala> MyEnumeration.nextValue(MyEnumeration(4))
res1: MyEnumeration.Value = Zero

Parsing command line args and executing a function in scala

I am trying to parse commandline arguments and execute a function that takes the parameters upon successful extraction of the parameters. I have an object called CurrencyExchangeRunner where the main method is. I have envisioned the structure of the class as follows:
object CurrencyExtractionRunner {
def main(args:Array[String]){
parseArgs(args){
(currencyType,currencyTypeArgs) =>
CurrencyExchanger(curencyType,currencyTypeArgs){
(exchanger) => exchanger.startExchange
}
}
}
}
}
What I want to accomplish above is to parse the arguments using parseArgs(args), get the (currencyType,currencyTypeArgs) as parameters and pass those into the CurrencyExchanger factory object and then that would return the appropriate exchanger on which I will execute the startExchange method. This is what I have envisioned but I am a little clueless on how would I go about creating this flow. The first thing I tried was to create a trait that parses the command-line args as follows(I am using the jcommander library for the commandline parse):
object Args {
#Parameter(
names = Array("-h", "--help"), help = true)
var help = false
#Parameter(
names = Array("-c", "--currency-type"),
description = "Type of currency exchange that needs to be performed",
required = true)
var currencyType: String = null
#Parameter(
names = Array("-d", "--denominations"),
description = "Specific denominations to be used during the exchage")
var exchangeDenomination: String = null
#Parameter(
names = Array("-s", "--someotheroptionalarg"),
description = "Additional argument for a specific currency exchange")
var someOtherOptionalArg: String = null
}
trait ParseUtils {
//How do I do this, take the args and return a function.
def parseArgs(args: Array[String]){
val jCommander = new JCommander(Args, args.toArray: _*)
if (Args.help) {
jCommander.usage()
System.exit(0)
}
//What do I do now? How do I proceed with executing the function with
//the specific arguments?
//What do I need to do to wrap the commandline arguments so that it could
//be passed to the next function
}
}
I am pretty stuck here since I am not sure how would I make the code flexible enough to take the arbitrary sequence of commandline args and execute the next step which is the factory that returns that takes these arguments and returns the correct exchanger.
It will be great if someone could point me in the right direction.
I'm not sure why you'd use such unusual syntax to pass return values to the following methods.
I would go for a simpler solution that looks like
trait ParseUtils {
//Why would you return a function here?
//Is it a strict constraint you need to fulfill?
def parseArgs(args: Array[String]): (String, String) {
val jCommander = new JCommander(Args, args.toArray: _*)
if (Args.help) {
jCommander.usage()
System.exit(0)
}
//This is the return value of the method, a pair of parameters
(Args.currencyType, Args.exchangeDenomination)
//If you need to embed additional params, you should append them to existing one
// or you could create optional values from the Args members...
// e.g. (Args.currencyType, Args.exchangeDenomination, Option(Args.someOtherOptionalArg))
// with return type (String, String, Option[String])
}
}
object CurrencyExtractionRunner with ParseUtils {
def main(args:Array[String]){
val (currencyType,currencyTypeArgs) = parseArgs(args)
CurrencyExchanger(currencyType,currencyTypeArgs).startExchange
}
}
case class CurrencyExchanger(currencyType: String, currencyTypeArgs: String) {
def startExchange = //implementation details using the costructor arguments
}
Alternative solution
since I prefer parseArgs to be more "functional" I'd change it to
trait ParseUtils {
def parseArgs(args: Array[String]): Option[(String, String)] {
val jCommander = new JCommander(Args, args.toArray: _*)
if (Args.help) {
jCommander.usage()
None
} else
Some(Args.currencyType, Args.exchangeDenomination)
}
}
object CurrencyExtractionRunner with ParseUtils {
def main(args:Array[String]){
parseArgs(args).foreach {
case (currencyType,currencyTypeArgs) =>
CurrencyExchanger(currencyType,currencyTypeArgs).startExchange
}
}
}
case class CurrencyExchanger(currencyType: String, currencyTypeArgs: String) {
def startExchange = //implementation details using the costructor arguments
}

Scala default parameters and null

I have a method like this:
def aMethod(param: String = "asdf") = {
...
}
If the method is called as follows, then param is given the default value "asdf":
aMethod() ...
But what I would like, is that if the method is called with null, then the default value would also be applied:
aMethod(null) //inside the method, I can use `param` and it has the value "asdf".
Whats the best way to do this in Scala? I can think of pattern matching or a simple if statement.
Pattern matching
def aMethod(param: String = null) {
val paramOrDefault = param match {
case null => "asdf"
case s => s
}
}
Option (implicitly)
def aMethod(param: String = null) {
val paramOrDefault = Option(param).getOrElse("asdf")
}
Option (explicitly)
def aMethod(param: Option[String] = None) {
val paramOrDefault = param getOrElse "asdf"
}
The last approach is actually the most idiomatic and readable once you get use to it.
def aMethod(param: String = null) = {
val p =
if(param == null)
"asdf"
else
param
println(p)
}
But the question must be asked: why allow null? Would Option be possible in your case? For this you could do:
def aMethod(param: Option[String]) = {
val p = param.getOrElse("asdf")
println(p)
}
This makes it clear that your method expects the possibility of a "null" argument.
If the method has just one or two default parameters that can be set to null consider this pattern:
// please note that you must specify function return type
def aMethod (x:String = "asdf"):String = if (x==null) aMethod() else {
// aMethod body ...
x
}
There are some benefits:
The method definition clearly indicates the parameter's default value.
The correct default value can be picked by Scala tools, including ScalaDoc.
There is no need to define an additional value to substitute for the original parameter within the method body - less room for mistakes, easier to reason.
The pattern is fairly concise.
Furthermore, consider the following scenario:
trait ATrait {
def aMethod (x:String = "trait's default value for x"):String
}
class AClass extends ATrait {
....
}
Clearly, here we need to extend the trait, whilst preserving the original default value. Any of the patterns that involve initially setting the parameter to null followed by a check and actual default value will break the contract established by the trait:
class AClass extends ATrait {
// wrong, breaks the expected contract
def aMethod(x: String = null):String = {
val xVal = if (x == null) "asdf" else x
...
}
}
Indeed in this scenario the only way to preserve the original value from ATrait will be:
class AClass extends ATrait {
override def aMethod (x:String):String = if (x==null) aMethod() else {
... // x contains default value defined within ATrait
}
}
However, in the scenario when there are more than one or two default parameters that can be set to null the pattern starts getting rather messy:
// two parameters
def aMethod (x:String = "Hello",y:String = "World"):String =
if (x==null) aMethod(y=y) else
if (y==null) aMethod(x=x) else {
// aMethod body ...
x + " " + y
}
// three parameters
def aMethod (x:String = "Hello",y:String = " ",z:String = "World"):String =
if (x==null) aMethod(y=y,z=z) else
if (y==null) aMethod(x=x,z=z) else
if (z==null) aMethod(x=x,y=y) else {
// aMethod body ...
x + y + z
}
Still when overriding an existing contract this might be the only way to honour the original default values.