【问题标题】:Can I mimic Scala SIP-18-syle imports?我可以模仿 Scala SIP-18-syle 导入吗?
【发布时间】:2015-07-27 22:15:01
【问题描述】:

Scala SIP 18 提供了一种强制用户提供导入语句以使用某些高级或不安全语言功能的方法。例如,要使用higher kinded types,您需要

import scala.language.higherKinds

否则您将收到编译器警告,告诉您正在使用高级功能。

有什么方法可以在我自己的库中重现或模仿这种行为?例如我可能有:

trait MongoRepository[E <: Entity] {
  val casbahCollection: com.mongodb.casbah.MongoCollection
}

我已将casbahCollection 公开,以便将底层集合公开给用户以备不时之需。但这真的不是我希望我的用户做的事情,因为它是一个泄漏的抽象。所以我想强迫他们做这样的事情:

import my.library.mongo.leakyAbstraction

在做这样的事情之前:

widgetRepo.casbahCollection.find()

有可能吗?有没有什么方法可以提供一种类似的行为,比仅仅在文档中放置一个丑陋的警告更有效?

【问题讨论】:

    标签: scala


    【解决方案1】:

    你可以用隐含的方式伪造它,类似于Await.resultscala.concurrent 中的工作方式。

    首先创建一个sealed trait,它表示直接访问您的 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

    【讨论】:

    • 谢谢,太好了!我刚刚使用隐式转换有类似的想法,但您的想法更优雅。
    • 关于在范围内需要leakyAbstraction 的库代码,我可以使MongoRepo 具有private[library] coll: com.mongodb.casbah.MongoCollectiondef cashbahCollection(implicit permit: CanAccessMongo) = coll。所以在图书馆里我只需要访问coll
    猜你喜欢
    • 2022-08-15
    • 1970-01-01
    • 1970-01-01
    • 2016-07-20
    • 2018-07-26
    • 1970-01-01
    • 2016-07-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多