gpt4 book ai didi

scala - 类标签和路径相关的类型,具有蛋糕图案的味道

转载 作者:行者123 更新时间:2023-12-02 04:53:47 24 4
gpt4 key购买 nike

我正在从事一个精巧的项目,我正试图让我的数据库层在不同的配置文件之间轻松交换,以便在内存数据库上编写测试。这个问题是受这个问题的启发,但它与 slick 本身没有任何关系。

我对依赖类型没有太多经验,在我的例子中,我有以下特征,我用它来从数据库中抽象出一些类型:

trait Types {
type A <: SomeType
type B <: SomeOtherType
val bTag: ClassTag[B]
}

然后我有另一个特征,基本上是我的(人造)蛋糕图案的一部分:

trait BaseComponent {
type ComponentTypes <: Types

val a: Types#A
implicit val bTag: ClassTag[Types#B]
}

然后我有一个组件的实际实现,如下所示:

trait DefaultTypes {
type A = SomeConcreteType
type B = SomeOtherConcreteType
val bTag = implicitly[ClassTag[B]]
}

trait DefaultBaseComponent extends BaseComponent {
type ComponentTypes = DefaultTypes
val ct = new ComponentTypes {}

implicit val bTag = ct.bTag
}

我需要这个标签,因为稍后服务会需要它(在我的实际实现中,我使用这个类型来抽象不同数据库库抛出的不同类型的异常);我很确定有更好的方法来完成我想做的事情。

如果我没有实例化 ComponentTypes 特性来获取标签,并且我在 DefaultBaseComponent 中移动隐式调用代码,它将调用一个 null 来代替类标签。我需要有一种方法来引用我正在使用的实际类型(不同的 AB 我在不同的环境中)并且我需要这样做在其他组件中不知道它们是哪些实际类型。

我的解决方案有效、编译并通过了我为其编写的所有测试,任何人都可以帮助我改进它吗?

谢谢!

最佳答案

您的示例对于所有这些 DefaultComponent 有点不清楚 - 也许更具体的示例(例如 DatabaseService/MysqlDatabaseService)会使它更清楚?

您需要将 ClassTag 传递到抽象的任何地方 - 当您拥有具体类型时,您只能“召唤”一个。您可能希望将值及其标签的概念打包:

trait TaggedValue[A] {val a: A; val ct: ClassTag[A]}
object TaggedValue {
def apply[A: ClassTag](a1: A) =
new TaggedValue[A] {
val a = a1
val ct = implicitly[ClassTag[A]]
}
}

但这只是一个方便的事情。您还可以将一些 trait 转换为 abstract class,允许您使用 [A: ClassTag] 隐式传递标签,但显然这会影响您可以多重继承哪些类。

如果您遇到了 null,这听起来像是特征初始化顺序问题,但如果没有更具体的错误消息,则很难提供帮助。您可以通过将一些 val 替换为 def 或使用早期初始化程序来解决此问题。

关于scala - 类标签和路径相关的类型,具有蛋糕图案的味道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25165941/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com