I have been bitten a number of times by a situation like this:
trait MyTrait {
val implementMe: String
val upper = implementMe.toUpperCase
}
class MyClass(s: String) extends MyTrait {
override val implementMe: String = s
}
val c = new MyClass("Hello, World")
println(c.upper)
In this example, everything compiles but the last line throws a NullPointerException at runtime, (I assume) because upper is computed before implementMe is actually defined.
I know I can fix it by changing upper to a def or a lazy val but it seems like this should be caught at compile time rather than runtime. Am I doing something wrong/is there a way this sort of problem can be detected at compile time? Is there a reason the compiler allows this?
The problem is initialization, as you've stated. As far as I know, there is no way to detect this at compile time. There is a bit of a trick, called early initialization, that allows you to work around this while avoiding def or lazy val (if that is your goal):
class MyClass(s: String) extends { override val implementMe: String = s } with MyTrait
Related
Consider the following case:
trait A {
protected val mydata = ???
def f(args) = ??? //uses mydata
}
class B
class C
class D(arg1: String) extends B with A {
override val mydata = ??? /// some calculation based on arg1
}
class E(arg1: String) extends C with A{
override val mydata = ??? /// some calculation based on arg1
}
A must be a trait as it is used by different unrelated classes. The problem is how to implement the definition of mydata.
The standard way (suggested in many places would be to define mydata as def and override it in the children. However, if f assumes mydata never changes then it can cause issues when some child extends with a function which changes between calls instead of with a val.
Another way would be to do:
trait A {
protected val mydata = g
protected def g()
}
The problem with this (beyond adding another function) is that if g depends on construction variables in the child then these must become members of the child (which can be a problem for example if the data is large and given in the construction):
class D(arg1: Seq[String]) {
def g() = ??? // some operation on arg1
}
If I leave the val in the trait as abstract I can reach issues such as those found here).
What I am looking for is a way to define the value of the val in the children, ensuring it would be a val and without having to save data for late calculations. Something similar as to how in java I can define a final val and fill it in the constructor
The standard way (suggested in many places would be to define mydata as def and override it in the children... If I leave the val in the trait as abstract I can reach issues such as those found here).
This is a common misunderstanding, shown in the accepted answer to the linked question as well. The issue is implementing as a val, which you require anyway. Having a concrete val which is overridden only makes it worse: abstract one can at least be implemented by a lazy val. The only way to avoid the issue for you is to ensure mydata is not accessed in a constructor of A or its subtypes, directly or indirectly, until it's initialized. Using it in f is safe (provided f is not called in a constructor, again, which would be an indirect access to mydata).
If you can ensure this requirement, then
trait A {
protected val mydata
def f(args) = ??? //uses mydata
}
class D(arg1: String) extends B with A {
override val mydata = ??? /// some calculation based on arg1
}
class E(arg1: String) extends C with A{
override val mydata = ??? /// some calculation based on arg1
}
is exactly the correct definition.
If you can't, then you have to live with your last solution despite the drawback, but mydata needs to be lazy to avoid similar initialization order issues, which would already give the same drawback on its own.
I tried using an abstract val in a trait to initialize another value. I got a NullPointerException. I boiled the behaviour down to a minimal test case:
trait MessagePrinter {
val message: String
println(message)
}
class HelloPrinter extends MessagePrinter {
val message = "Hello World"
}
val obj = new HelloPrinter()
println(obj.message)
This little program yields the following result:
null
Hello World
I was under the impression that a val may never change. Is this expected behaviour or is it a compiler bug? How can I work around this issue and print Hello World during initialization?
By section 5.1 of the Scala specification, super classes are initialized first. Even though vals cannot normally be reinstantiated, they do start with a default initial value during construction. You can either use def, which has different semantics:
trait MessagePrinter {
def message: String
println(message)
}
class HelloPrinter extends MessagePrinter {
def message = "Hello World"
}
Or you might consider switching things around like so:
class HelloPrinter extends { val message = "Hello World" } with MessagePrinter
In which case the super classes are evaluated in order, so that the MessagePrinter initialization should work as desired.
You should use def in both cases.
One of the sources describing this behaviour is "Scala Puzzlers" Puzzler 4:
The following rules control the initialization and overriding behavior
of vals:
Superclasses are fully initialized before subclasses.
Members are initialized in the order they are declared.
When a val is overridden, it can still only be initialized once.
Like an abstract val, an overridden val will have a default initial value during the construction of superclasses.
Given the trait (simplified)
trait A {
val eventStream: EventStream
val credentialsStorage = // something here
val userStorage = // something here
val crypto = // something here
...
lazy val authSvc = new CoreAuthentication(credentialsStorage, new AuthenticationProviderResolver, userStorage, eventStream, crypto)
}
class T extends A with TraitProvidingEventStream with FlatSpec with [lot of another traits here] {
val eventStream = systemFromTraitProvidingEventStream.eventStream
"This" should "work" in {
println(authSvc) // this is "magic"
val user = authSvc.doSomethingWithUser(...);
}
}
if I remove line marked as //this is "magic", then I will get NullPointerException on the next line, so authSvc is null.
What may be wrong there?
I wasn't be able to create clean small test case for that, usually this works well
This came up once on the ML: If an exception is thrown when initializing a lazy val, the val is null; but you can attempt to init again and it can work magically. (That is, the "initialized" bit flag for the lazy val is not set on the first failed attempt to initialize.)
I think the case on the ML had to do with init order of vals in traits, so maybe that's your problem. It's infamously dangerous to rely on it, hence the advice to use defs in traits. See Luigi's comment on DelayedInit.
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 */ }
What I'd like to achieve is having a proper implementation for
def dynamix[A, B](a: A): A with B
I may know what B is, but don't know what A is (but if B has a self type then I could add some constraints on A).
The scala compiler is happy with the above signature, but I could not yet figure out how the implementation would look like - if it is possible at all.
Some options that came to my mind:
Using reflection/dynamic proxy.
Simplest case: A is an interface on Java level + I can instantiate B and it has no self type. I guess it would not be too hard (unless I run into some nasty, unexpected problems):
create a new B (b), and also a proxy implementing both A and B and using an invocation handler delegating to either a or b.
If B can not be instantiated I could still create a subclass of it, and do as it was described above. If it also has a self type I would probably need some delegation here and there, but it may still work.
But what if A is a concrete type and I can't find a proper interface for it?
Would I run into more problems (e.g. something related to linearization, or special constructs helping Java interoperability)?
Using a kind of wrapping instead of a mixin and return B[A], a is accessible from b.
Unfortunately in this case the caller would need to know how the nesting is done, which could be quite inconvenient if the mixing in/wrapping is done several times (D[C[B[A]]]) as it would need to find the right level of nesting to access the needed functionality, so I don't consider it a solution.
Implementing a compiler plugin. I have zero experience with it but my gut feeling is that it would not be trivial. I think Kevin Wright's autoproxy plugin has a bit similar goal, but it would not be enough for my problem (yet?).
Do you have any other ideas that might work? Which way would you recommend? What kind of "challenges" to expect?
Or should I forget it, because it is not possible with the current Scala constraints?
Intention behind my problem:
Say I have a business workflow, but it's not too strict. Some steps have fixed order, but others do not, but at the end all of them has to be done (or some of them required for further processing).
A bit more concrete example: I have an A, I can add B and C to it. I don't care which is done first, but at the end I'll need an A with B with C.
Comment: I don't know too much about Groovy but SO popped up this question and I guess it's more or less the same as what I'd like, at least conceptional.
I believe this is impossible to do strictly at runtime, because traits are mixed in at compile-time into new Java classes. If you mix a trait with an existing class anonymously you can see, looking at the classfiles and using javap, that an anonymous, name-mangled class is created by scalac:
class Foo {
def bar = 5
}
trait Spam {
def eggs = 10
}
object Main {
def main(args: Array[String]) = {
println((new Foo with Spam).eggs)
}
}
scalac Mixin.scala; ls *.class returns
Foo.class Main$.class Spam$class.class
Main$$anon$1.class Main.class Spam.class
While javap Main\$\$anon\$1 returns
Compiled from "mixin.scala"
public final class Main$$anon$1 extends Foo implements Spam{
public int eggs();
public Main$$anon$1();
}
As you can see, scalac creates a new anonymous class that is loaded at runtime; presumably the method eggs in this anonymous class creates an instance of Spam$class and calls eggs on it, but I'm not completely sure.
However, we can do a pretty hacky trick here:
import scala.tools.nsc._;
import scala.reflect.Manifest
object DynamicClassLoader {
private var id = 0
def uniqueId = synchronized { id += 1; "Klass" + id.toString }
}
class DynamicClassLoader extends
java.lang.ClassLoader(getClass.getClassLoader) {
def buildClass[T, V](implicit t: Manifest[T], v: Manifest[V]) = {
// Create a unique ID
val id = DynamicClassLoader.uniqueId
// what's the Scala code we need to generate this class?
val classDef = "class %s extends %s with %s".
format(id, t.toString, v.toString)
println(classDef)
// fire up a new Scala interpreter/compiler
val settings = new Settings(null)
val interpreter = new Interpreter(settings)
// define this class
interpreter.compileAndSaveRun("<anon>", classDef)
// get the bytecode for this new class
val bytes = interpreter.classLoader.getBytesForClass(id)
// define the bytecode using this classloader; cast it to what we expect
defineClass(id, bytes, 0, bytes.length).asInstanceOf[Class[T with V]]
}
}
val loader = new DynamicClassLoader
val instance = loader.buildClass[Foo, Spam].newInstance
instance.bar
// Int = 5
instance.eggs
// Int = 10
Since you need to use the Scala compiler, AFAIK, this is probably close to the cleanest solution you could do to get this. It's quite slow, but memoization would probably help greatly.
This approach is pretty ridiculous, hacky, and goes against the grain of the language. I imagine all sorts of weirdo bugs could creep in; people who have used Java longer than me warn of the insanity that comes with messing around with classloaders.
I wanted to be able to construct Scala beans in my Spring application context, but I also wanted to be able to specify the mixins to be included in the constructed bean:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:scala="http://www.springframework.org/schema/scala"
xsi:schemaLocation=...>
<scala:bean class="org.cakesolutions.scala.services.UserService" >
<scala:with trait="org.cakesolutions.scala.services.Mixin1" />
<scala:with trait="org.cakesolutions.scala.services.Mixin2" />
<scala:property name="dependency" value="Injected" />
<scala:bean>
</beans>
The difficulty is that Class.forName function does not allow me to specify the mixins. In the end, I extended the above hacky solution to Scala 2.9.1. So, here it is in its full gory; including bits of Spring.
class ScalaBeanFactory(private val beanType: Class[_ <: AnyRef],
private val mixinTypes: Seq[Class[_ <: AnyRef]]) {
val loader = new DynamicClassLoader
val clazz = loader.buildClass(beanType, mixinTypes)
def getTypedObject[T] = getObject.asInstanceOf[T]
def getObject = {
clazz.newInstance()
}
def getObjectType = null
def isSingleton = true
object DynamicClassLoader {
private var id = 0
def uniqueId = synchronized { id += 1; "Klass" + id.toString }
}
class DynamicClassLoader extends java.lang.ClassLoader(getClass.getClassLoader) {
def buildClass(t: Class[_ <: AnyRef], vs: Seq[Class[_ <: AnyRef]]) = {
val id = DynamicClassLoader.uniqueId
val classDef = new StringBuilder
classDef.append("class ").append(id)
classDef.append(" extends ").append(t.getCanonicalName)
vs.foreach(c => classDef.append(" with %s".format(c.getCanonicalName)))
val settings = new Settings(null)
settings.usejavacp.value = true
val interpreter = new IMain(settings)
interpreter.compileString(classDef.toString())
val r = interpreter.classLoader.getResourceAsStream(id)
val o = new ByteArrayOutputStream
val b = new Array[Byte](16384)
Stream.continually(r.read(b)).takeWhile(_ > 0).foreach(o.write(b, 0, _))
val bytes = o.toByteArray
defineClass(id, bytes, 0, bytes.length)
}
}
The code cannot yet deal with constructors with parameters and does not copy annotations from the parent class’s constructor (should it do that?). However, it gives us a good starting point that is usable in the scala Spring namespace. Of course, don’t just take my word for it, verify it in a Specs2 specification:
class ScalaBeanFactorySpec extends Specification {
"getTypedObject mixes-in the specified traits" in {
val f1 = new ScalaBeanFactory(classOf[Cat],
Seq(classOf[Speaking], classOf[Eating]))
val c1 = f1.getTypedObject[Cat with Eating with Speaking]
c1.isInstanceOf[Cat with Eating with Speaking] must_==(true)
c1.speak // in trait Speaking
c1.eat // in trait Eating
c1.meow // in class Cat
}
}