在抽象类中推断应该可供编译器使用的多个泛型类型

Flo*_*her 11 generics inheritance scala slick-2.0

我正在为我的play2/slick2项目开发一个抽象的CRUD-DAO.为了拥有方便的类型安全的主要ID我使用Unicorn作为额外的抽象和方便在光头MappedToColumnBaseType.

Unicorn提供了一个基本的CRUD-DAO类BaseIdRepository,我想进一步扩展它以满足项目的特定需求.班级的签名是

class BaseIdRepository[I <: BaseId, A <: WithId[I], T <: IdTable[I, A]]
  (tableName: String, val query: TableQuery[T])
  (implicit val mapping: BaseColumnType[I])
  extends BaseIdQueries[I, A, T]
Run Code Online (Sandbox Code Playgroud)

这导致DAO实现看起来像

class UserDao extends 
  BaseIdRepository[UserId, User, Users]("USERS", TableQuery[Users])
Run Code Online (Sandbox Code Playgroud)

这对我来说似乎是多余的.我能够提供tableNamequeryT我自己的抽象DAO给我以下签名

abstract class AbstractIdDao[I <: BaseId, A <: WithId[I], T <: IdTable[I, A]] 
  extends BaseIdRepository[I,A,T](TableQuery[T].baseTableRow.tableName, TableQuery[T])
Run Code Online (Sandbox Code Playgroud)

是否有可能在斯卡拉以某种方式推断类型IA做出类似以下可能的签名?(Users是一个类扩展IdTable)

class UserDao extends AbstractIdDao[Users]
Run Code Online (Sandbox Code Playgroud)

这可能没有运行时反射吗?如果仅通过运行时反射:如何在类定义中使用Manifest以及在响应式应用程序中对性能的影响有多大?

另外,因为我对这门语言还很陌生并独立工作:这是scala中的好习惯吗?

谢谢你的帮助.随意批评我的问题和英语.当然,改进将提交给Unicorn git-repo

编辑: 实际上,TableQuery[T].baseTableRow.tableName, TableQuery[T]由于所需的错误类类型但是T找不到,IDEA表面上很好,scalac不是.

DCK*_*ing 0

至于你的第一个问题,我在使用 Slick 时也遇到过这种情况。但如果你仔细想想,你会发现你不能在编译时做到这一点。这是因为此类型信息是指定类型参数之间关系所必需的。如果不这样做,您将能够构造类型BaseIdRepository没有意义的类,例如IdTables表不表示投影的地方。由于每个关系都需要名称,因此需要 3 个命名类型参数。如果省略第一个,则可以构造一个 IdRepository 而无需包含 Id 的投影;如果省略第二个,则可能会出现一个没有 ID 列的表;如果省略第三个,则可以查询不具有表和带有 ID 的投影的组合的表。您的应用程序中可能没有定义当前会违反任何这些规则的类型,但编译器不知道这一点。提供正确的类型信息是不可避免的。

至于你的第二个问题,仅仅因为你认为语法冗长而使用反射是非常不可取的。如果您可以通过简单地提供类型参数来保证类型安全,我建议您这样做。以这种方式编写 Scala 的品味和风格非常糟糕。具有讽刺意味的是,在 Unicorn 中使用类型安全 ID,然后通过反射来破解其类型安全。

此外, aManifest不是您想要的清单不允许您向编译器提供较少的类型信息,它只允许您更灵活地指定这样做的位置。它允许您在编译时利用编译器的类型知识来避免类型擦除带来的一些问题。您在这里面临的问题与类型擦除无关,因此Manifests 不起作用。最后,运行时反射在这里不会有太大帮助,因为如果您尚未提供类型信息,Slick 的内部函数将不允许您进行编译。

所以是的,你想要的东西是不可能的。Scala(和 Slick)在编译时需要完整的信息,没有任何技巧可以有效地规避这一点。