How to create package object which will be available to all the inner packages in scala? - 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.

Related

Importing object without class

I'm trying to import an object from another .scala file that doesn't exist inside a class. I've found you can import a class like in here Scala, importing class. Is there a way to import an object without having a class around it?
Thanks
Importing a class and importing an object work the same in scala.
If you have a class
package com.package1
class MyClass{}
and an object
package com.package2
object MyObject{}
You import both the exact same way
package com.package3
import com.package1.MyClass
import com.package2.MyObject
import syntax is the same no matter what you are importing, whether it's an object, a class, a trait, a method, or a field
Yes, Scala can do exactly what you ask, and this is used frequently. Here is an example:
object Blah {
val x = 1
val y = "hello"
}
object Main extends App {
import Blah._
println(s"x=$x; y=$y")
}
Output is:
x=1; y=hello
You can also import members of a class instance, which blew my mind the first time I saw it.
If you are talking about companion objects, they are not defined inside a class, but after the class definition:
class AClass {
def sayHello() = {
println(AClass.Hello)
}
}
object AClass {
private val Hello = "hello"
}
You should have no problem importing it.

package object definitions are not in scope

Inside of my package com.example.common I have a package.scala file:
package com.example.common
import scala.concurrent.Future
package object common extends MyPackage {
}
trait MyPackage extends MyFutures {
}
trait MyFutures {
type Funit = Future[Unit]
}
Now inside of this file I thought I can have the above in scope:
com.example.common.email
class EmailService() {
def send(name: String): Funit = {
}
}
But my alias type Funit isn't in scope and I get the error:
no found: type Funit
Your EmailService is not in the package containing your package object.
Your package object is inside com.package.common.common
Also you should name name your package object according to the package:
A package object package object p extends t adds the members of template to the package p. There can be only one package object per package. The standard naming convention is to place the definition above in a file named package.scala that's located in the directory corresponding to package p.
So you should have the following
a file named com/example/common/package.scala
containing package object common
declared inside package com.example
import scala.concurrent.Future
package object common extends MyPackage {
}
trait MyPackage extends MyFutures {
}
trait MyFutures {
type Funit = Future[Unit]
}
// in the same file (you mentioned "Now inside of this file I thought I can have the above in scope:")
package common {
package email {
class EmailService() {
def send(name: String): Funit = ???
}
}
}
This way, since you're already in the common package:
package com.example.common
import scala.concurrent.Future
object `package` extends MyPackage {
}
trait MyPackage extends MyFutures {
}
trait MyFutures {
type Funit = Future[Unit]
}
and to make common._ visible:
package com.example.common
package email
class EmailService() {
def send(name: String): Funit = ???
}

How do I import for all classes in a scala package simultaneously?

Consider package com.example . Inside package com.example we have two classes named Foo and Bar.
There is also an object named Baz located in a package named com.other . Is there a way I can import Baz to Foo and Bar using only one import statement? In other words, how can I define a block of imports that affects all classes (Foo and Bar) in a package (com.example)?
I tried the following, but it is not working.
// filename:package.scala location:com/example
package com {
package object example {
import other.Baz
}
}
// filename:Foo.scala location:com/example
package com.example {
class Foo {
// Baz should be in scope here
Baz.methodCall()
}
class Bar {
// Baz should be in scope here too
Baz.methodCall()
}
}
I tried searching extensively, but I'm not sure how to phrase this scenario. Thanks for the help.
You could try binding it to a val.
package com {
package object example {
val Baz = other.Baz
}
}
If you don't want Baz to be visible to the outside:
package com {
package object example {
private[example] val Baz = other.Baz
}
}

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.
}

Scala package object constructor

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.