Not able to hide Scala Class from Import

Viewed 301

Wrote this code

scala> import scala.collection.immutable.{Stream => _}
scala> Stream(1, 2, 3)
res0: scala.collection.immutable.Stream[Int] = Stream(1, ?)

But shouldn't the second line fail? because I hid the Stream class from import in line 1? why is it still visible?

I also tried

scala> import scala.collection.immutable.{Stream => DoNotUse}
import scala.collection.immutable.{Stream=>DoNotUse}

scala> Stream(1, 2, 3)
res1: scala.collection.immutable.Stream[Int] = Stream(1, ?)

Again, this is still visible.

3 Answers

Here's an example with the new -Yimports in 2.13.

$ cat S.scala

package mystream

class Stream[A]

object MyPredef {
  type Stream[A] = mystream.Stream[A]
}

Imports later in the list shadow earlier ones:

$ scala -Yimports:java.lang,scala,scala.Predef,mystream.MyPredef
Welcome to Scala 2.13.0 (OpenJDK 64-Bit Server VM 11.0.1)

scala> new Stream[Int]
res0: mystream.Stream[Int] = mystream.Stream@65fe2691

It's not as convenient as the hypothetical syntax

-Yimports:java.lang._,scala.{Stream=>_, _},scala.Predef._

which would support your use case more directly.

Alternatively, it's usual to put aliases in an enclosing package object:

package object mystuff {
  type Stream[A] = mystream.Stream[A]
}

and

scala> :pa
// Entering paste mode (ctrl-D to finish)

package mystuff {
  class C { def f = new Stream[Int] }
}

// Exiting paste mode, now interpreting.


scala> new mystuff.C().f
res1: mystream.Stream[Int] = mystream.Stream@715fa8c5

but the alias is scoped to those subpackages and not any compilation unit.

You can't "unimport" an imported value. If you write import scala.collection.immutable.{Stream => _}, you will just add another import to your namespace.


Here's another example:

import scala.collection.immutable.{Stream => Foo}
import scala.collection.immutable.{Stream => Bar}

The second line does not remove the first import. Both lines just add one additional import to your namespace. You can now refer to Stream as Foo and Bar.


Why do you wan't to remove an import? If you don't want to use the class, just don't use it. There's no need to remove an import. It does not add a dependency on Stream or any other drawback at runtime, imports are a compiletime only concept.

Maybe you have your own class named Stream that you want to use. Therefore it is not necessary it "remove" the default Stream import. Just import your class. This will shadow the default import.

import foo.Stream
val x: Stream[_] = ??? // this variable has type `foo.Stream`

// Here we have another import of a class with the same name.
// This shadows the first import, so any occurence of `Stream`
// does from now on refer to `bar.Stream`.
import bar.Stream
val x: Stream[_] = ??? // This variable has type `bar.Stream`
Related