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

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

Related

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 = ???
}

Can we do conditional imports in Scala?

say I have the following code:
package my
class Foo
class Bar extends Foo
object Chooser {
val isFoo = true
}
I import Foo as:
import my.{Foo => MyClass}
I want to be able to do something like:
If Chooser.isFoo, then:
import my.{Foo => MyClass}
else:
import my.{Bar => MyClass}
I have used Foo in my code as something like this:
object MyObj {
val a = new MyClass
// ...
}
Are there any hidden features of Scala that let me use Bar in place of Foo without modifying the code of MyObj at all. Also what would be the best way to design such code in future so that such extensions are easy?
There isn't but I'm guessing you are more interested in different implementations at runtime than in conditional type import. Your Chooser.isFoo sounds like something that happens during runtime and not in the type system.
One example of how you could do it, since the common type for Foo and Bar is Foo:
val a: Foo =
if (Chooser.isFoo) new my.Foo
else new my.Bar
Edit based on your edit: you could delay the choice by having an abstract type or a type parameter, like so:
class MyObj[T :> Foo] {
val a: T
}
val anInstance = new MyObj[Foo]
val anotherInstance = new MyObj[Bar]
Note the type bound that says that T must be a subclass of Foo, or else you wouldn't know anything about what you can do with a T.
Happen to see this old post & a little curious why it can't do conditional imports in Scala? Maybe old version limit, not sure? But see this, we can import in any place of scala code.
For your scenario, it could be:
try.scala:
package my
class Foo {
}
class Bar extends Foo
object Chooser {
val isFoo = true
}
object MyObj extends App {
if (Chooser.isFoo) {
import my.{Foo => MyClass}
val a = new MyClass
println(a)
} else {
import my.{Bar => MyClass}
val a = new MyClass
println(a)
}
}
run output:
C:\abc\abc>scalac try.scala
C:\abc\abc>scala my.MyObj
my.Foo#6f4a47c7

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

Scala package delcaration - one way causes package objects visible, other makes it not?

In foo/bar/my_package/package.scala:
package foo.bar
package object my_package {
type SomeType = java.lang.String
}
Then, in foo/bar/my_package/my_sub/MyClass.scala
package foo.bar.my_package.my_sub
class MyClass {
var x: SomeType = _
}
This fails to compile; SomeType isn't found. If I change MyClass.scala to
package foo.bar.my_package
package my_sub
class MyClass {
var x: SomeType = _
}
Everything works fine. What is the difference!?!??!
(This is Scala 2.8.1)
Package declarations, like imports, give you access to everything inside them. So when you
package foo.bar.my_package
then you have everything available that you would if you did
import foo.bar.my_package._
Furthermore, declaring a package on a single line means that everything below belongs to that package:
package foo.bar.my_package {
package my_sub {
class MyClass { var x: SomeType = _ }
}
}
(which is equivalent to:
package foo.bar.my_package
package my_sub
class MyClass { var x: SomeType = _ }
)
so you can see how the contents of foo.bar.my_package ought to be in scope in this case. In the other case, you only have the contents of foo.bar.my_package.my_sub available, which does not include SomeType.
It's a visibility question.
package foo.bar.my_package.my_sub
class MyClass {
var x: SomeType = _
}
When you declare x, the following things are visible:
Every member of MyClass
Everything inside foo.bar.my_package.my_sub
Every member of scala.Predef
Everything inside scala
Everything inside java.lang
The type SomeType is not inside any of those.
On the other hand, when you do:
package foo.bar.my_package
package my_sub
class MyClass {
var x: SomeType = _
}
Then the visibility is:
Every member of MyClass
Everything inside foo.bar.my_package.my_sub
Everything inside foo.bar.my_package
Every member of scala.Predef
Everything inside scala
Everything inside java.lang
And SomeType is inside foo.bar.my_package, which is the second line.
A related question is why it works this way. You can get a start here, though there's a question precisely about that. I don't much like the answer to that question, though, as it really doesn't touch the reasons for it. It does link to a page on scala-lang about new features of Scala 2.8, in which Odersky explains the reasons.