I am trying to do a very basic serialization of a very simple case class in Scala:
import org.scalatest.wordspec.AnyWordSpecLike
import java.io.{ByteArrayOutputStream, ObjectOutputStream}
class PersistenceSpec extends AnyWordSpecLike{
case class TestClass(name: String) extends Serializable
def serializeSomething(): ByteArrayOutputStream = {
val testItem = TestClass("My Thing")
val bos: ByteArrayOutputStream = new ByteArrayOutputStream()
val oos = new ObjectOutputStream(bos)
oos.writeObject(testItem)
bos
}
"serializeSomething" when {
"executed" must {
"successfully serialize" in {
val outputStream = serializeSomething()
println(outputStream.toString())
}
}
}
}
When I run this test I get a java.io.NotSerializableException on the call to oos.writeObject(testItem), which makes no sense, since case classes automatically implement Serializable, and this is the simplest possible example.
However, if I paste the code for TestClass and serializeSomething() into repl, I am able to call the function, and it works just fine.
What is different when calling my function via scalatest, vs repl that would cause this exception?
One final note: If I change the call from oos.writeObject(testItem) to oos.writeObject("Hello"), it works fine, even when run from scalatest.
You need to define TestClass outside of PersistenceSpec.
Inner class instances automatically get a reference to the instance of the outer class. So, when you write it out, it tries to serialize the PersistenceSpec instance as well, and that of course fails.
Editing due to a combination of an overly complex example and not cleary stating my intentions.
I have a class that designers will extend from and build. To keep code clean I would like to be able to do a combination of actions when specific classes are instantiated.
I know that I can use a Companion Object with custom apply() to do most of this, and would work with the exception that I sort of need to know the class that is instantiating the specific class (and I'm trying to avoid passing this as a parameter).
class Apple{}
class Orange{}
class MyBase{
val allApples = ListBuffer[Apple]()
val allOranges = ListBuffer[Orange]()
}
//User defined classes extending MyBase
class SomeNewClass extends MyBase{
val apple1 = new Apple //we would want to add apple1 to the allApples List
val apple2 = new Apple
val orange1 = new Orange
}
class AnotherClass extends MyBase{
val someClass = new SomeNewClass
val apple1 = new Apple
}
So you can see that I want to be able to add the Apple instances to the allApples ListBuffer and same for the oranges. I'd like to be able to do this without requiring an addApple type of method. The problem is, I have no reference to SomeNewClass or AnotherClass (or whatever else the designer would make). I could have an implicit like the following:
class Apple()(implicit myBaseCaller : MyBase){
myBaseCaller.addApple(this)
}
class MyBase{
implicit val myself : MyBase = this
//excluded for clarity
}
Instantiating a new Apple or Orange outside of a class that extends MyBase would be a violation of the DSL in this particular case.
So I don't disagree that the best solution would be an explicit method to addApples, however I'm trying to see if there is a solution that is easier on the coding.
There may not be a decent way to do it, which would be ok. In this case I don't mind a little extra overhead in the base classes to make the extended classes easier to write.
Removed Original Question as too complicated
Instantiating a new Apple or Orange outside of a class that extends MyBase would be a violation of the DSL in this particular case.
It's not clear from the context whether that would be desirable or not.
In any case, have you considered what might be accomplished with a private constructor and a public auxiliary constructor?
import scala.collection.mutable.ListBuffer
class MyBase{
class Apple private (lb :ListBuffer[Apple]) {
lb += this
def this() = this(allApples)
}
class Orange private (lb :ListBuffer[Orange]) {
lb += this
def this() = this(allOranges)
}
val allApples = ListBuffer[Apple]()
val allOranges = ListBuffer[Orange]()
}
class SomeNewClass extends MyBase{
val apple1 = new Apple
val apple2 = new Apple
val orange1 = new Orange
}
class AnotherClass extends MyBase{
val someClass = new SomeNewClass
val apple1 = new Apple
}
val snc = new SomeNewClass
val ac = new AnotherClass
snc.allApples.size //res0: Int = 2
snc.allOranges.size //res1: Int = 1
ac.allApples.size //res2: Int = 1
ac.allOranges.size //res3: Int = 0
I'm trying to make a generic implicit provider which can create an implicit value for a given type, something in the lines of:
trait Evidence[T]
class ImplicitProvider[T] {
class Implementation extends Evidence[T]
implicit val evidence: Evidence[T] = new Implementation
}
To use this implicit, I create a val provider = new ImplicitProvider[T] instance where necessary and import from it import provider._. This works fine as long as there is just one instance. However sometimes implicits for several types are needed in one place
case class A()
case class B()
class Test extends App {
val aProvider = new ImplicitProvider[A]
val bProvider = new ImplicitProvider[B]
import aProvider._
import bProvider._
val a = implicitly[Evidence[A]]
val b = implicitly[Evidence[B]]
}
And this fails to compile with could not find implicit value for parameter and not enough arguments for method implicitly errors.
If I use implicit vals from providers directly, everything starts to work again.
implicit val aEvidence = aProvider.evidence
implicit val bEvidence = bProvider.evidence
However I'm trying to avoid importing individual values, as there are actually several implicits inside each provider and the goal is to abstract them if possible.
Can this be achieved somehow or do I want too much from the compiler?
The issue is that when you import from both objects, you're bringing in two entities that have colliding names: evidence in aProvider and evidence in bProvider. The compiler cannot disambiguate those, both because of how its implemented, and because it'd be a bad idea for implicits, which can already be arcane, to be able to do things that cannot be done explicitly (disambiguating between clashing names).
What I don't understand is what the point of ImplicitProvider is. You can pull the Implementation class out to the top level and have an object somewhere that holds the implicit vals.
class Implementation[T] extends Evidence[T]
object Evidence {
implicit val aEvidence: Evidence[A] = new Implementation[A]
implicit val bEvidence: Evidence[B] = new Implementation[B]
}
// Usage:
import Evidence._
implicitly[Evidence[A]]
implicitly[Evidence[B]]
Now, there is no name clash.
If you need to have an actual ImplicitProvider, you can instead do this:
class ImplicitProvider[T] { ... }
object ImplicitProviders {
implicit val aProvider = new ImplicitProvider[A]
implicit val bProvider = new ImplicitProvider[B]
implicit def ImplicitProvider2Evidence[T: ImplicitProvider]: Evidence[T]
= implicitly[ImplicitProvider[T]].evidence
}
// Usage
import ImplicitProviders._
// ...
I have the following macro defining a class and returning an instance of that class (with Scala 2.10.2 and the macro plugin):
def test[T] = macro testImpl[T]
def testImpl[T : c.WeakTypeTag](c: Context): c.Expr[Any] = {
import c.universe._
val className = newTypeName("Test")
c.Expr { q"""
class $className {
def method = 1
}
new $className
"""}
}
When I call the macro:
case class Cat(name: String)
val t = test[Cat].method
I get the following error:
method method in class Test cannot be accessed in Test
val t = test[Cat].method
^
My overall goal is to use vampire methods and to use quasi-quotes to describe the generated class. How can I solve this error?
In my post on vampire methods I mention this workaround for this bug. For some reason you currently aren't able to see an anonymous class's methods on the instance returned from the macro unless you create a wrapper class that extends the class with the methods and return an instance of that, instead.
You're seeing the same bug from a slightly different angle. You've named the class with the methods you want to see on the returned instance's structural type, but you still need a wrapper. The following will work:
c.Expr { q"""
class $className {
def method = 1
}
new $className {}
"""}
Note that all I've done is add a pair of brackets to the line creating the instance, so that I get an instance of an anonymous class extending $className instead of just a $className.
I have no idea what's behind this bug, and I'm not sure if Eugene knows more. I did recently confirm that it's still around in the latest build of 2.11.
Hey guys,
im working on a project in scala and i encountered very weird problem. This is a part of the code :
class Entity(val id:String){
override def toString = id
}
class RequirementType
case class DependsEither(t:List[(Entity,Int)]) extends RequirementType
case class Depends(t:(Entity,Int)) extends RequirementType
class BuildableEntity(override val id:String,
val mineralCost:Int,
val gasCost:Int,
val buildTime:Int,
val buildCount:Int,
val supplyCount:Int,
val req:List[RequirementType],
val onBuildStart: GameState => GameState,
val onBuildFinish: GameState => GameState
)extends Entity(id)
class SimpleBuilding(id:String,
mineralCost:Int,
gasCost:Int,
buildTime:Int,
req:List[RequirementType]
) extends BuildableEntity(id,mineralCost,gasCost,buildTime,1,0,req:::List(ConsumesOnStart((Drone,1))),{s=>s},{x=>x})
object SpawningPool extends SimpleBuilding("spawningPool",200,0,65,List(DependsEither(List((Hatchery,1),(Lair,1),(Hive,1)))))
object Lair extends SimpleBuilding("lair",150,100,80,List(ConsumesOnFinish(Hatchery,1),Depends(SpawningPool,1)))
object InfestationPit extends SimpleBuilding("infestationPit",100,100,50,List(DependsEither(List((Lair,1),(Hive,1)))))
Now, when i call println(Lair.req), it sometimes prints as
List(ConsumesOnFinish((hatchery,1)), Depends((null,2)), ConsumesOnStart((drone,1)))
and sometimes as
List(ConsumesOnFinish((hatchery,1)),
Depends((spawningPool,2)), ConsumesOnStart((drone,1)))
Please, if anyone has any idea about what could be going wrong, i would love you for ever. I have no clue why is it act as it does. I have more extensions of SimpleBuilding but they seem to be working properly
EDIT:
I should also mention that the outcome changes after compilation. I mean that when i run unit test it sometimes appear as null and sometimes as proper instance.
This is indeed a case of circular dependency and initialization. Here is a shorter version of your issue:
class X(val x: List[X])
object A extends X(List(B))
object B extends X(List(A))
object Main {
def main(args:Array[String]) {
println("A.x: " + A.x)
println("B.x: " + B.x)
}
}
This will print this:
$ scala -cp classes Main
A.x: List(B$#143c8b3)
B.x: List(null)
You can use by names parameter to allow object construction to finish before you use it:
class X(x0: => List[X]) {
lazy val x = x0
}
object A extends X(List(B))
object B extends X(List(A))
The fix works on the small test case:
$ scala -cp classes Main
A.x: List(B$#1feca64)
B.x: List(A$#6d084b)
Based on this you may want to change req:List[RequirementType] to req0: => List[RequirementType] and add a lazy val req = req0.
If that works for you, we should retitle the question to mention object initialization and circular dependencies. Note this is very similar to this question/answer.
Lair use SpawningPool in its constructor and reciprocally. But at that time, the other doesn't exists.
You've got recursive definitions in constructors, and although I believe that is supported, it looks like something's going wrong. Can you try lazy vals instead and see if the problem goes away? That is,
object X extends C("this",that,1) { /* code */ }
becomes
lazy val X = new C("this",that,1) { /* code */ }