Scala SIP 18 provides a way to force users to provide an import statement to use certain advanced or unsafe language features. For instance, in order to use higher kinded types, you need to
import scala.language.higherKinds
or you will get a compiler warning telling you you are using an advanced feature.
Is there any way that I can reproduce or mimic this behavior in my own library? For example I may have:
trait MongoRepository[E <: Entity] {
val casbahCollection: com.mongodb.casbah.MongoCollection
}
I have made the casbahCollection
public to expose the underlying collection to the user in case they need it. But it's really not something I want my users to do because it's a leaky abstraction. So I want to force them to do something like this:
import my.library.mongo.leakyAbstraction
Before doing something like this:
widgetRepo.casbahCollection.find()
Is it possible? Is there some way I might provide a similar behavior that's a little more effective than just placing a big ugly warning in the docs?
You could fake it with an implicit, similar to the way Await.result
works in scala.concurrent
.
First create a sealed trait
that represents a "permit" to directly access your DAO:
@implicitNotFound("Import my.library.mongo.leakyAbstraction to directly access Mongo")
sealed trait CanAccessMongo
And then an object that extends it:
implicit object leakyAbstraction extends CanAccessMongo
These must be in the same file. By making CanAccessMongo
sealed, code outside the same file will not be able to extend it.
Then in MongoRepository
make cashbahCollection
a function (change val
to def
). You'll probably want a private val that actually creates it, but we need the function to limit access.
def cashbahCollection(implicit permit: CanAccessMongo) = ...
Now users of your library will have to bring leakyAbstraction
into scope in order to call that function. If they don't, they'll get the error message specified in implicitNotFound
.
The obvious downside is that all your library code will have to have leakyAbstraction
in scope as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With