Scala package object constructor - scala

When and how is the Scala Package object constructor called?
I have two classes:
Package.scala
package my;
package object entities {
//Some initialization code in constructor
}
Classy.scala
package my.entities;
case class Classy {
}
I am trying to have the entities constructor to have already been executed by the time an object of Classy is created.

The package object is translated into a normal java class file called package.class IIRC. From then on I assume it behaves like any normal Java class, thus it is loaded and instantiated when it is first referenced. In Scala, that means you need to define some method or val in the package object, then access it from outside. In your case, you may try calling it from the constructor of Classy, or from the code which instantiates Classy.
Update
OK, here is some code I ran to test what I described above:
// package.scala
package some
package object pkg {
println("package created!")
def func() { println("func called") }
}
// C.scala
package some.pkg
class C {
println("created C")
}
// G.scala
package some.pkg
object G {
println("creating G")
func()
println("created G")
}
// PackageTester.scala
package some.pkg
object PackageTester extends App {
val c = new C
val g = G
}
And the output is:
created C
creating G
package created!
func called
created G
Which proves that Scala package objects are created lazily, only when they are actually referenced. And in fact the same is true for "normal" Scala objects, as demonstrated by G above.

Related

How to invoke a main method in a nested object?

The following code has main methods in objects A and A.B. I can invoke A from the command line. Is there any way to invoke A.B?
object A {
def main(args : Array[String]) = ()
object B {
def main(args : Array[String]) = ()
}
}
What I think is happeing: Scala compiles object A to class A$ and A.B to A$B$. Neither of these classes has a static method. Scala creates an additional class A with a static main method that delegates to A$.main. But Scala does not compile an equivalent class for A.B because the compiler special-cases top-level classes with main methods.
If the above description is correct then there is no way to invoke A.B on the command line. Is it? If so is there a reason for this implementation?
So, as you noticed, object A { ... } ends up as a class A$, not A, it has a main method, but it is not static.
Scala objects are singleton instances, not just classes with a bunch of static methods.
So, to be able to run scala A from command line, scalac generates another class A, with a static method main, that calls A$.MODULE$.main ...
This is a special piece of extra logic, needed to comply with jvm's assumptions of how to look for main when it starts from command line.
The compiler only does it for top-level objects, that have a main method and do not have a companion class (because if they did, the name would clash with the generated class).
Why it does not do it for nested classes? I don't think there some sort of a reason specifically preventing it (like the name clash I mentioned above), probably, just because nobody asked for it.
The inner object B is not visible from outside. To invoke its main method, you have to provide an interface in A, for example from its main method, so you can pass the args without further ado:
object A {
def main(args : Array[String]) = {
println ("outer A.main")
B.main (args)
}
object B {
def main(args : Array[String]) = {
println ("inner B.main")
}
}
}
Invokation:
scala -howtorun:object A
outer A.main
inner B.main
Test:
scala -howtorun:object A.B
java.lang.ClassNotFoundException: A.B

What's the scope of a private top-level class with access qualifier set to the same package where the class is defined in Scala?

I have read this article to better understand Scala scoping rules.
Everything seemed clear until I ran into some code on GitHub that was like this:
package x.y.z
private[z] class ExampleClass {
// class body
}
As you can see, we have a private top-level class, and there's an access qualifier to modify the scope of that class, but it's set to the very same package where the class is defined. If the access qualifier was set to an enclosing scope (e.g. package y) I would perfectly get it, but like this I can't understand the difference with simply declaring the class as private:
package x.y.z
private class ExampleClass {
// class body
}
So what is the difference between the two snippets posted above?
NOTE: I don't know if it's of any relevance, but in the same file a companion object for the class was defined and simply declared as private (with no access qualifiers).
In the example you provided both modifiers have the same effect. Difference would be more apparent if you had an enclosing class/object.
Compiles:
package x.y.z
object OuterExampleClass {
private[z] class ExampleClass()
}
object AnotherObject {
val ec = new OuterExampleClass.ExampleClass()
}
Fails to compile:
package x.y.z
object OuterExampleClass {
private class ExampleClass() // no [z] !!!
}
object AnotherObject {
val ec = new OuterExampleClass.ExampleClass() // error
}
with message:
class ExampleClass in object OuterExampleClass cannot be accessed in
object x.y.z.OuterExampleClass

How to create package object which will be available to all the inner packages in scala?

I have package structure like this.
In file A/B/package.scala
package A
package object B {
def foo = "Hello world"
}
In file A/B/xyz.scala
package A.B
object bar {
def baz() {
println(foo())
}
}
This won't throw error. It will work as expected. But if I try to use like:
In file A/B/C/biz.scala
package A.B.C
object biz {
def baz() {
println(foo())
}
}
It will throw error as foo is not in the scope of inner package. I need to have global access to foo(). How can I achieve it?
One way is to import A.B like import A.B._.
But it will import all the classes in A.B package which I don't want to do.
Is there any other way to achieve the same?
The best fit is import A.B.foo (and other specific methods you need). You can also make foo available in a non-package object and import all of its methods. Of course, you can also have them in the package object:
package A.B
abstract class ABMethods { def foo = ... }
package A
package object B extends ABMethods { ... }
package A.B
object Foo extends ABMethods { ... }
But there is no way to have all of package object methods available without all classes of A.B.

Scala importing a file in all files of a package

I need to use an implicit ordering that has been defined in an object in a file
abc
in the following way:
object abc{
implicit def localTimeOrdering: Ordering[LocalDate] = Ordering.fromLessThan(_.isBefore(_))
}
So, I make a package object
xyz
inside a file 'package.scala' that in turn is in the package 'xyz' that has files in which I need the implicit ordering to be applicable. I write something like this:
package object xyz{
import abc._
}
It does not seem to work. If I manually write the implicit definition statement inside the package object, it works perfectly. What is the correct way to import the object (abc) such that all of its objects/classes/definitions can be used in my entire package 'xyz' ?
You cannot import the implicit conversions in that way, you will have to:
Manually write them inside the object:
package obj {
implicit def etc//
}
Or obtain them via inheritance/mixins:
package obj extends SomeClassOrTraitWithImplicits with AnotherTraitWithImplicits {
}
For this reason, you usually define your implicit conversions in traits or class definitions, that way you can do bulk import with a single package object.
The usual pattern is to define a helper trait for each case.
trait SomeClass {
// all the implicits here
}
object SomeClass extends SomeClass {}
Doing this would allow you to:
package object abc extends SomeClass with SomeOtherClass with AThirdClass {
// all implicits are now available in scope.
}

How to add a new Class in a Scala Compiler Plugin?

In a Scala Compiler Plugin, I'm trying to create a new class that implement a pre-existing trait. So far my code looks like this:
def trait2Impl(original: ClassDef, newName: String): ClassDef = {
val impl = original.impl
// Seems OK to have same self, but does not make sense to me ...
val self = impl.self
// TODO: implement methods ...
val body = impl.body
// We implement original
val parents = original :: impl.parents
val newImpl = treeCopy.Template(impl, parents, self, body)
val name = newTypeName(newName)
// We are a syntheic class, not a user-defined trait
val mods = (original.mods | SYNTHETIC) &~ TRAIT
val tp = original.tparams
val result = treeCopy.ClassDef(original, mods, name, tp, newImpl)
// Same Package?
val owner = original.symbol.owner
// New symbol. What's a Position good for?
val symbol = new TypeSymbol(owner, NoPosition, name)
result.setSymbol(symbol)
symbol.setFlag(SYNTHETIC)
symbol.setFlag(ABSTRACT)
symbol.resetFlag(INTERFACE)
symbol.resetFlag(TRAIT)
owner.info.decls.enter(symbol)
result
}
But it doesn't seem to get added to the package. I suspect that is because actually the package got "traversed" before the trait that causes the generation, and/or because the "override def transform(tree: Tree): Tree" method of the TypingTransformer can only return one Tree, for every Tree that it receives, so it cannot actually produce a new Tree, but only modify one.
So, how do you add a new Class to an existing package? Maybe it would work if I transformed the package when "transform(Tree)" gets it, but I that point I don't know the content of the package yet, so I cannot generate the new Class this early (or could I?). Or maybe it's related to the "Position" parameter of the Symbol?
So far I found several examples where Trees are modified, but none where a completely new Class is created in a Compiler Plugin.
The full source code is here: https://gist.github.com/1794246
The trick is to store the newly created ClassDefs and use them when creating a new PackageDef. Note that you need to deal with both Symbols and trees: a package symbol is just a handle. In order to generate code, you need to generate an AST (just like for a class, where the symbol holds the class name and type, but the code is in the ClassDef trees).
As you noted, package definitions are higher up the tree than classes, so you'd need to recurse first (assuming you'll generate the new class from an existing class). Then, once the subtrees are traversed, you can prepare a new PackageDef (every compilation unit has a package definition, which by default is the empty package) with the new classes.
In the example, assuming the source code is
class Foo {
def foo {
"spring"
}
}
the compiler wraps it into
package <empty> {
class Foo {
def foo {
"spring"
}
}
}
and the plugin transforms it into
package <empty> {
class Foo {
def foo {
"spring"
}
}
package mypackage {
class MyClass extends AnyRef
}
}