I am trying to stub a case class which has structure similar to below code.
case class Employee[T](name:T) {
def greet(str:String):String = {
"Hi, "+ str + ":" + name
}
def farewell(str:String):String = {
"Bye, "+ str + ":" + name
}
}
However, when creating a stub like this:
val emp = stub[Employee[String]],
gives the following error:
type mismatch;
found : T
required: String
val emp = stub[Employee[String]]
How can i Stub this class.
Stubbing cases classes is usually avoided but assuming you are using ScalaMock try extending it first with some defaults, for example
class StrEmployee extends Employee[String](null)
val emp = stub[StrEmployee]
(emp.greet _).when("aa").returns("bb")
assert(emp.greet("aa") == "bb")
Related
can any one explain the following output. I have a simple Scala code like this..
object compOrNotTest {
def main(args: Array[String]) {
var emp = new Employee("tom", 20)
println(emp)
println(Employee.adult(emp))
Employee.printName("Roland", 38)
var emp2 = new Employee("Harry", 37)
Employee.printName(emp2)
}
}
class Employee(name: String, age: Int) {
val ageOfEmplyedd: Int = age
val nameEmp: String = name
override def toString() = this.name + " age : " + this.age
def printName() {
println("name is in Class " + nameEmp)
}
}
object Employee {
def adult(emp: Employee) = {
if (emp.ageOfEmplyedd > 18)
true
else
false
}
def printName(name: String, age: Int) = {
val emp1 = new Employee(name, age)
println("Name is : " + emp1.printName())
}
def printName(emp1: Employee) = {
//val emp1 = new Employee(name, age)
println("Name is : "+ emp1.printName())
}
}
And the output I am getting is
tom age : 20
true
name is in Class Roland
Name is : ()
name is in Class Harry
Name is : ()
My question is that why , when I am calling from Companion object I am getting only Name is : (). I am expecting something like Name is : name is in Class Roland. Please help me out to understand the how scala works in this case. Thanks a lot
The return type of Employee.printName (in class Employee) is Unit. This is because this function was declared using procedure syntax (a function declaration with no = sign in it, which has been deprecated and which will no longer be supported in a future version of Scala) that has an associated return type of Unit. The Unit value that is returned is represented in Scala as ().
The following function declarations are equivalent:
// Using (soon-to-be-deprecated) procedure syntax.
def printName() {
println("name is in Class " + nameEmp)
}
// Using an explicit return type.
def printName(): Unit = {
println("name is in Class " + nameExp)
}
// Using an inferred return type (note "=" in declaration). The last statement is the call
// to println, which returns Unit, so a return type of Unit is inferred.
def printName() = {
println("name is in Class " + nameExp)
}
If you wanted to return the string that was printed, you would need something like this:
def printName() = {
val s = "name is in Class " + nameEmp
println(s)
s
}
Or, using an explicit return type, instead of inferring it from the last statement:
def printName(): String = {
val s = "name is in Class " + nameEmp
println(s)
s
}
I'm just learning Scala, and I have these three files:
abstract class Animal() {
name
sound
}
class Dog(n : String) extends Animal {
name = n
val sound = "Boof"
}
trait Speaking extends Animal {
def speak(n : String, s : Sound) : String = {
println(s + "! I'm " + n + "!")
}
}
In my main method, I have the following code:
d = new Dog("Maddie") with Speaking
println(d.speak)
When I run this code, I get error: not found: value d
Put val before d if you haven't declared it before.
I think it should be something like this:
abstract class Animal() {
def name: String // You need a type(String) and a qualifier(def)
def sound: String // the same
}
class Dog(n : String) extends Animal {
// Type is not obligatory here, as it is inherited from Animal.
// But you still need a qualifier(val)
val name = n
val sound = "Boof"
}
trait Speaking extends Animal {
// This method doesn't need those params,
// since this trait extends Animal,
// so it has access to name and sound defined there.
def speak: String = {
sound + "! I'm " + name + "!"
}
}
Your main method remains the same.
I'm learning Scala, and I was attempting to import from 2 scrips in different classes, but, I get an error, and I don't know why.
This class, in Summer.scala, is where I try to import the singleton object from class ChecksumAccumulator.
import ChecksumAccumulator.calculate
object Summer{
def main(args: Array[String]): Unit= {
for (arg <- args)
println(arg + " : " + calculate(arg))
}
}
Class ChecksumAccumulator, with the singleton object ChecksumAccumulator.
object ChecksumAccumulator {
/*
When a singleton object shares the same name
with a class, it is called that class's companion object.
*/
private val cache = mutable.Map.empty[String, Int]
def calculate(s: String): Int =
if (cache.contains(s))
cache(s)
else {
val acc = new ChecksumAccumulator
//The object with the same name of the class can acces to the private members.
//println(acc.sum)
for (c <- s)
acc.add(c.toByte)
val cs = acc.checksum()
cache += (s -> cs)
cs
}
def showMap() : Unit = {
for(base:String <- cache.keys)
println(cache(base))
}
//def showMap(): String = { var cadena = cache("Every value is an object.") + " "+ cache("Every value is an object. per second time!!"); cadena }
}
This script throw this mistake
scala Summer.scala
Summer.scala:8: error: not found: object ChecksumAccumulator import
ChecksumAccumulator.calculate ^ Summer.scala:14: error: not found:
value calculate println(arg + " : " + calculate(arg)) ^ two errors
found
It seems like it's a duplicated question, but I can't yet mark questions as duplicated nor comment on them.
If that is all your code, it means you're missing:
class ChecksumAccumulator { ... }
Because you're trying to create an instance of this class:
val acc = new ChecksumAccumulator
And it's impossible to achieve with just:
object ChecksumAccumulator { ... }
Check out this answer about exactly the same code example. There is the missing definition of class ChecksumAccumulator :
https://stackoverflow.com/a/8681616/5100014
Just make sure to paste it into the same file with object ChecksumAccumulator
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.
Having a trait
trait Persisted {
def id: Long
}
how do I implement a method that accepts an instance of any case class and returns its copy with the trait mixed in?
The signature of the method looks like:
def toPersisted[T](instance: T, id: Long): T with Persisted
This can be done with macros (that are officially a part of Scala since 2.10.0-M3). Here's a gist example of what you are looking for.
1) My macro generates a local class that inherits from the provided case class and Persisted, much like new T with Persisted would do. Then it caches its argument (to prevent multiple evaluations) and creates an instance of the created class.
2) How did I know what trees to generate? I have a simple app, parse.exe that prints the AST that results from parsing input code. So I just invoked parse class Person$Persisted1(first: String, last: String) extends Person(first, last) with Persisted, noted the output and reproduced it in my macro. parse.exe is a wrapper for scalac -Xprint:parser -Yshow-trees -Ystop-after:parser. There are different ways to explore ASTs, read more in "Metaprogramming in Scala 2.10".
3) Macro expansions can be sanity-checked if you provide -Ymacro-debug-lite as an argument to scalac. In that case all expansions will be printed out, and you'll be able to detect codegen errors faster.
edit. Updated the example for 2.10.0-M7
It is not possible to achieve what you want using vanilla scala. The problem is that the mixins like the following:
scala> class Foo
defined class Foo
scala> trait Bar
defined trait Bar
scala> val fooWithBar = new Foo with Bar
fooWithBar: Foo with Bar = $anon$1#10ef717
create a Foo with Bar mixed in, but it is not done at runtime. The compiler simply generates a new anonymous class:
scala> fooWithBar.getClass
res3: java.lang.Class[_ <: Foo] = class $anon$1
See Dynamic mixin in Scala - is it possible? for more info.
What you are trying to do is known as record concatenation, something that Scala's type system does not support. (Fwiw, there exist type systems - such as this and this - that provide this feature.)
I think type classes might fit your use case, but I cannot tell for sure as the question doesn't provide sufficient information on what problem you are trying to solve.
Update
You can find an up to date working solution, which utilizes a Toolboxes API of Scala 2.10.0-RC1 as part of SORM project.
The following solution is based on the Scala 2.10.0-M3 reflection API and Scala Interpreter. It dynamically creates and caches classes inheriting from the original case classes with the trait mixed in. Thanks to caching at maximum this solution should dynamically create only one class for each original case class and reuse it later.
Since the new reflection API isn't that much disclosed nor is it stable and there are no tutorials on it yet this solution may involve some stupid repitative actions and quirks.
The following code was tested with Scala 2.10.0-M3.
1. Persisted.scala
The trait to be mixed in. Please note that I've changed it a bit due to updates in my program
trait Persisted {
def key: String
}
2. PersistedEnabler.scala
The actual worker object
import tools.nsc.interpreter.IMain
import tools.nsc._
import reflect.mirror._
object PersistedEnabler {
def toPersisted[T <: AnyRef](instance: T, key: String)
(implicit instanceTag: TypeTag[T]): T with Persisted = {
val args = {
val valuesMap = propertyValuesMap(instance)
key ::
methodParams(constructors(instanceTag.tpe).head.typeSignature)
.map(_.name.decoded.trim)
.map(valuesMap(_))
}
persistedClass(instanceTag)
.getConstructors.head
.newInstance(args.asInstanceOf[List[Object]]: _*)
.asInstanceOf[T with Persisted]
}
private val persistedClassCache =
collection.mutable.Map[TypeTag[_], Class[_]]()
private def persistedClass[T](tag: TypeTag[T]): Class[T with Persisted] = {
if (persistedClassCache.contains(tag))
persistedClassCache(tag).asInstanceOf[Class[T with Persisted]]
else {
val name = generateName()
val code = {
val sourceParams =
methodParams(constructors(tag.tpe).head.typeSignature)
val newParamsList = {
def paramDeclaration(s: Symbol): String =
s.name.decoded + ": " + s.typeSignature.toString
"val key: String" :: sourceParams.map(paramDeclaration) mkString ", "
}
val sourceParamsList =
sourceParams.map(_.name.decoded).mkString(", ")
val copyMethodParamsList =
sourceParams.map(s => s.name.decoded + ": " + s.typeSignature.toString + " = " + s.name.decoded).mkString(", ")
val copyInstantiationParamsList =
"key" :: sourceParams.map(_.name.decoded) mkString ", "
"""
class """ + name + """(""" + newParamsList + """)
extends """ + tag.sym.fullName + """(""" + sourceParamsList + """)
with """ + typeTag[Persisted].sym.fullName + """ {
override def copy(""" + copyMethodParamsList + """) =
new """ + name + """(""" + copyInstantiationParamsList + """)
}
"""
}
interpreter.compileString(code)
val c =
interpreter.classLoader.findClass(name)
.asInstanceOf[Class[T with Persisted]]
interpreter.reset()
persistedClassCache(tag) = c
c
}
}
private lazy val interpreter = {
val settings = new Settings()
settings.usejavacp.value = true
new IMain(settings, new NewLinePrintWriter(new ConsoleWriter, true))
}
private var generateNameCounter = 0l
private def generateName() = synchronized {
generateNameCounter += 1
"PersistedAnonymous" + generateNameCounter.toString
}
// REFLECTION HELPERS
private def propertyNames(t: Type) =
t.members.filter(m => !m.isMethod && m.isTerm).map(_.name.decoded.trim)
private def propertyValuesMap[T <: AnyRef](instance: T) = {
val t = typeOfInstance(instance)
propertyNames(t)
.map(n => n -> invoke(instance, t.member(newTermName(n)))())
.toMap
}
private type MethodType = {def params: List[Symbol]; def resultType: Type}
private def methodParams(t: Type): List[Symbol] =
t.asInstanceOf[MethodType].params
private def methodResultType(t: Type): Type =
t.asInstanceOf[MethodType].resultType
private def constructors(t: Type): Iterable[Symbol] =
t.members.filter(_.kind == "constructor")
private def fullyQualifiedName(s: Symbol): String = {
def symbolsTree(s: Symbol): List[Symbol] =
if (s.enclosingTopLevelClass != s)
s :: symbolsTree(s.enclosingTopLevelClass)
else if (s.enclosingPackageClass != s)
s :: symbolsTree(s.enclosingPackageClass)
else
Nil
symbolsTree(s)
.reverseMap(_.name.decoded)
.drop(1)
.mkString(".")
}
}
3. Sandbox.scala
The test app
import PersistedEnabler._
object Sandbox extends App {
case class Artist(name: String, genres: Set[Genre])
case class Genre(name: String)
val artist = Artist("Nirvana", Set(Genre("rock"), Genre("grunge")))
val persisted = toPersisted(artist, "some-key")
assert(persisted.isInstanceOf[Persisted])
assert(persisted.isInstanceOf[Artist])
assert(persisted.key == "some-key")
assert(persisted.name == "Nirvana")
assert(persisted == artist) // an interesting and useful effect
val copy = persisted.copy(name = "Puddle of Mudd")
assert(copy.isInstanceOf[Persisted])
assert(copy.isInstanceOf[Artist])
// the only problem: compiler thinks that `copy` does not implement `Persisted`, so to access `key` we have to specify it manually:
assert(copy.asInstanceOf[Artist with Persisted].key == "some-key")
assert(copy.name == "Puddle of Mudd")
assert(copy != persisted)
}
While it's not possible to compose an object AFTER it's creation, you can have very wide tests to determine if the object is of a specific composition using type aliases and definition structs:
type Persisted = { def id: Long }
class Person {
def id: Long = 5
def name = "dude"
}
def persist(obj: Persisted) = {
obj.id
}
persist(new Person)
Any object with a def id:Long will qualify as Persisted.
Achieving what I THINK you are trying to do is possible with implicit conversions:
object Persistable {
type Compatible = { def id: Long }
implicit def obj2persistable(obj: Compatible) = new Persistable(obj)
}
class Persistable(val obj: Persistable.Compatible) {
def persist() = println("Persisting: " + obj.id)
}
import Persistable.obj2persistable
new Person().persist()