I was wondering about this behaviour of scala class which is shown in the code snippet. The execution of following code prints hi , my confusion is what goes on in the background that without any method and field definition the invocation of TestClass executes the bare code? Also why is such kind of bare code writing within a class is allowed ?
class TestClass {
if(true)
println("hi")
}
object TestObject extends App{
val ci = new TestClass
}
The body of a class, object or trait (except for method definitions) is its (primary) constructor. It's more complicated for classes and object extending DelayedInit (or App, which extends DelayedInit).
The special syntax of 'bare' code inside classes is Scala's equivalent of Java's initializers / anonymous constructors that use braces around the code. Both initializers in Java and the code in your Scala class are executed on object creation, which is what you do inside your TestObject when calling the TestClass constructor with new.
Related
Hi I'm newbie in Scala.
As far as I know there are 2ways to make entry point in scala, one is define main method with object and the other is extending App trait.
I wondered how App trait works, so I checked the source for App trait, but there are full of confusing code...
The code said that the App has initCodes which are extended from App trait, and these are added in delayedInit method that inherited from DelayedInit. Also the App trait has main method, which will be entry point.
But the What confusing me are
Who call delayedInit? Is it called before the main method is called?(I guess Yes)
Why initCodes is ListBuffer not a element? I think there is only one entry point in application, so I don't think it should be plural.
Where can I check these knowledge? I tried to search in document but I couldn't
Who call delayedInit? Is it called before the main method is called?(I guess Yes)
The delayedInit would be called automatically by the Scala compiler as the initialisation code of the object/class that extends the DelayedInit trait. I expand more on this answer below.
Why initCodes is ListBuffer not a element? I think there is only one entry point in application, so I don't think it should be plural.
Because it is possible to have a hierarchy of classes, where the initialisation code of each class in the hierarchy gets executed as part of executing the program. An example is also provided below.
Where can I check these knowledge? I tried to search in document but I couldn't.
I got to learn about the dynamics by reading the Scala docs and the links it points to. For example this https://github.com/scala/scala/releases/tag/v2.11.0 and https://issues.scala-lang.org/browse/SI-4330?jql=labels%20%3D%20delayedinit%20AND%20resolution%20%3D%20unresolved
I would now try to expatiate more on the answer above by going into more details into the workings of DelayedInit, and how the JVM specifies entry points to programs.
First of all, we have to understand that when Scala is run on the JVM, it still has to adhere to the JVM requirement for defining the entry point to your program, which is to provide the JVM with a class with a main method with signature of public static void main(String[]). Even though when we use the App trait, it might appear as if we are getting away from do this, but this is just an illusion, the JVM still needs to have access to a method with the signature public static void main(String[]). It is just that by extending App together with the mechanism of DelayedInit, Scala can provide this method on our behalf.
Second, it is also good to reiterate that code snippets found in the body of a class (or object) definition, would be the initialisation code of such a class/object and would be executed automatically when such is instantiated. In Java, it is more or less the code you put in the constructor block.
So for a class:
class Foo {
// code.
def method = ???
}
Whatever code is, it will be executed automatically when you call new Foo.
In case of an object
object Foo {
// code.
def method = ???
}
The code will be executed automatically without you having to call new since Scala would automatically make a singleton instance called Foo available for you.
So basically if anything is in the body definition, it gets executed automatically. You do not need to explicitly execute it.
Now to the DelayedInit trait. One thing to be aware of is that it provides us a mechanism to perform what can be called a compiler trick, where certain part of our code gets rewritten. This is one of the reason why it could be confusing to reason about. Because when you use it, what actually gets executed by the Scala compiler is not the code you reading but a slight modification of it. To understand what is going on, you then need to understand the ways the compiler alters the code.
The trick, the DelayedInit trait allows us to perform is to take the code that is part of the body of a class/object definition and turn it, into an argument that is passed by name, to the method delayedInit defined on DelayedInit.
Basically it rewrites this:
object Foo {
// some code
}
into
object Foo {
// delayedInt({some code})
}
This means instead of having // some code executed automatically, delayedInt is the method that is called automatically with // some code passed to it as arguments.
So anything that extends DelayedInit would have its initialisation code replaced by the method call delayedInt with the initialisation code passed as an argument. Hence why nobody needs to explicitly call the delayedInt method.
Now let use see how this then tie to the App trait and how the App trait is used to provide the entry point to a Scala application.
As you will notice, the delayedInit method on the DelayedInit trait does not provide any implementation. Hence the actual behaviour of delayedInit when it is called needs to be provided by something else that extends DelayedInit.
The App trait is such an implementation. And what does the App trait do? Two important thing related to the topic of discussion:
It provides an implementation of delayedInit which takes the initialisation code it is passed, and puts it in a ListBuffer.
It provides the main method def main(args: Array[String]) which satisfy the requirement of the JVM to have a method with public static void main(String[]) to serve as the entry point to a program. And what this main method does, is to execute whatever code placed in the ListBuffer.
The above characteristics of the App trait means that any object/class that extends it would have its initialisation code passed to delayedInit, which would then add it into a ListBuffer, and then the object/class extending it would now have a main method, which when called (most of the time by the JVM as the entry point) would run through the code in the ListBuffer and execute it.
Basically it turns this:
object Foo {
// some code
}
into this
object Foo {
// the implementation of delayedInt is to put `// some code` into a list buffer
delayedInt (// some code)
def main(args: Array[String]) = {
// the implementation below just runs through and execute the code found in list buffer that would have been populated by the call to delayedInt and
???
}
}
So why have a List buffer to store the code to be executed? Because, as I said above it is possible to have a hierarchy of classes, where the initialisation code of each class in the hierarchy gets executed as part of executing the program. To see this in action.
Given the following code snippet:
class AnotherClass {
println("Initialising AnotherClass")
}
trait AnotherTrait {
println("Initialising AnotherTrait")
}
trait YetAnotherTrait {
println("Initialising YetAnotherTrait")
}
object Runner extends AnotherClass with AnotherTrait with YetAnotherTrait with App {
println("Hello world")
}
When run would output the following:
Initialising AnotherClass
Initialising AnotherTrait
Initialising YetAnotherTrait
Hello world
So the individual initialisation code in the hierarchy that consists of AnotherClass, AnotherTrait and YetAnotherTrait gets added to the initCode list buffer, via the delayedInit method of the App trait, and then they get executed by the main method also provided by the App trait.
As you would have noticed by peeking into the source code, the whole mechanism of DelayedInt is deprecated and schedule for removal in the future.
delayedInit:-
The init hook. This saves all initialization code for execution within
main. This method is normally never called directly from user code.
Instead it is called as compiler-generated code for those classes and
objects (but not traits) that inherit from the DelayedInit trait and
that do not themselves define a delayedInit method.
App scala
delayedInit is deprecated since 2.11.0. Also, it has some outstanding bugs which are not fixed.
initCodes:-
I am not sure about the reason for defining the initCodes as ListBuffer.
Consider the following example Scala class and unit test:
class BrokenClass(s: String) {
private val len = s.length
def length(): Int = len
}
class BrokenTest extends FlatSpec with Matchers with MockFactory {
"A BrokenClass" should "stub correctly" in {
val stubThing = stub[BrokenClass]
(stubThing.length _) when () returns (10)
stubThing.length should equal (10)
}
}
In older versions of ScalaMock, this code would work. With Scala 2.12 and ScalaMock 3.6, I'm getting a NullPointerException because even though I'm creating a stub, it's still invoking the "s.length" line of the constructor of BrokenClass. So it's trying to dereference "s", which is null because I haven't passed anything to it because all I want is a stub that returns a specific value when a specific method is called.
Is there a way to create a stub without it trying to invoke the object's constructor? Why did this work in older versions?
ScalaMock generates subclasses using a macro definition.
That macro gets expanded/evaluated during the compiler run.
As mocks are subclasses, the constructors of the superclasses will be called - no exceptions.
You might be able to work around this using some cglib sorcery, but that is not something i am familiar with.
So this may have been possible in older ScalaMock versions but this feature is not coming back anytime soon with the current implementation.
another option is to actually subclass this thing yourself and mock the subclass
class NotSoBrokenClass extends BrokenClass("")
...
val nsb = mock[NotSoBrokenClass]
...
That works in some cases, but if the constructor depends on non-final method calls you'll see funny behaviour (e.g. NPEs) too.
Now i understand how my program runs after extending App trait .I went through this link to understand how App trait works . In the link it is mentioned that by extending App trait we are achieving lazy evaluation . Why i would need lazy evaluation ? How lazy evaluation better than direct call to main() instead of extending App trait ?
I think it's the other way around: we don't need lazy eval, but we use it behind the scenes because that's the only way to implement it. From the scaladoc:
The App trait can be used to quickly turn objects into executable
programs.
By using App trait you avoid the boilerplate of writing:
object MainApp {
def main(args: Array[String]): Unit = { ... }
}
There is no way to achieve this syntax: object MainApp extends App {...} with regular means because you would have to override main method to call your code. Thus you can use compiler trick with DelayedInit which will turn your object body into a function call which will be called from main - this is the way to connect your code to the main entry point.
The caveat mentioned by scaladoc is:
It should be noted that this trait is implemented using the
[[DelayedInit]] functionality, which means that fields of the object
will not have been initialized before the main method has been
executed.
which for me personally is a preferred way of doing things. This, in contrast, is different from static initializers in Java that are executed before main method is called.
I have a Java code that looks for annotations in static methods of a class.
processor.readStatics( MyClass.class ); // Takes Class<?>
How can I provide the methods of a scala companion object to this function from within scala?
class MyClass {
}
object MyClass {
def hello() { println("Hello (object)") }
}
I seems that:
MyClass$.MODULE$.getClass()
should be the answer. However, MyClass$ seems to be missing from scala (in 2.10, at least) and only visible to Java.
println( Class.forName("MyClass$.MODULE$") )
also fails.
Class name is MyClass$ (with the appropriate package name prepended).
println(Class.forName("MyClass$")) will print out "class MyClass$".
MyClass$.MODULE$ is the instance of the class, referencing the singleton object.
println(MyClass$.MODULE$ == MyClass) will print out "true" even though, when compiling, you will get a warning that this comparison always yields false :)
Note, that none of this works in repl for some reason. You need to actually create a .scala file, compile it with scalac, and run.
So, in java, use MyClass$ to reference the class of MyClass object statically, use MyClass$.MODULE$ to reference the singleton instance of MyClass object, use MyClass$.class or MyClass$.MODULE$.getClass() to reference the class of the singleton object dynamically, use Class.forName("MyClass$") to access it at runtime by name.
The shortest and type-safest solution is to simply use
MyClass.getClass
I would have hoped the following to work, but apparently scalac is not happy with it:
classOf[MyClass.type]
I find this kind of code is very common in Lift framework, written like this:
object BindHelpers extends BindHelpers {}
What does this mean?
In this case, BindHelpers is a trait and not a class. Let foo() to be a method defined in BindHelpers, to access it you can either.
Use it through the companion object: BindHelpers.foo()
Mix the trait BindHelpers in a class and thus be able to access the methods inside of it.
For instance:
class MyClass extends MyParentClass with BindHelpers {
val a = foo()
}
The same techniques is used in Scalatest for ShouldMatchers for instance.
You can find David Pollak's answer to the same question in the liftweb group.
It's interesting for an object to extend its companion class because it will have the same type as the class.
If object BindHelpers didn't extend BindHelpers, it would be of type BindHelpers$.
It might be that the pattern here is other. I don't know Lift to answer this, but there's a problem with object in that they are not mockable. So, if you define everything in a class, which can be mocked, and then just makes the object extend it, you can mock the class and use it instead of the object inside your tests.