Scala SIP 18提供了一种强制用户提供import语句以使用某些高级或不安全语言功能的方法。例如,要使用higher kinded types,您需要
keeplimits
或者您会收到编译器警告,告诉您正在使用高级功能。
有没有什么方法可以在我自己的库中重现或模仿这种行为?例如,我可能有:
import scala.language.higherKinds
我让trait MongoRepository[E <: Entity] {
val casbahCollection: com.mongodb.casbah.MongoCollection
}
public公开底层集合给用户,以备他们需要时。但它真的不是我希望我的用户做的事情,因为它是一个漏洞的抽象。所以我想强迫他们做这样的事情:
casbahCollection
在做这样的事情之前:
import my.library.mongo.leakyAbstraction
有可能吗?有没有什么方法可以提供类似的行为,比在文档中放置一个大丑陋的警告更有效?
答案 0 :(得分:8)
您可以使用隐式伪造它,类似于Await.result
中scala.concurrent
的工作方式。
首先创建一个sealed trait
代表一个&#34; permit&#34;直接访问你的DAO:
@implicitNotFound("Import my.library.mongo.leakyAbstraction to directly access Mongo")
sealed trait CanAccessMongo
然后是一个扩展它的对象:
implicit object leakyAbstraction extends CanAccessMongo
这些必须在同一个文件中。通过使CanAccessMongo
密封,同一文件外的代码将无法扩展它。
然后在MongoRepository
中设置cashbahCollection
一个函数(将val
更改为def
)。您可能想要一个实际创建它的私有val,但我们需要该函数来限制访问。
def cashbahCollection(implicit permit: CanAccessMongo) = ...
现在,您的图书馆用户必须将leakyAbstraction
带入范围才能调用该功能。如果他们没有,他们将收到implicitNotFound
中指定的错误消息。
明显的缺点是你的所有库代码都必须在范围内有leakyAbstraction
。