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

Scala 推断编译器应该可以使用的抽象类中的多个泛型类型,scala,generics,inheritance,slick-2.0,Scala,Generics,Inheritance,Slick 2.0,我正在为play2/slick2项目编写一个抽象的CRUD-DAO。为了方便地使用类型安全的主ID,我在slicksMappedTo&ColumnBaseType的基础上使用它作为额外的抽象和方便 Unicorn提供了一个基本的CRUD-DAO类BaseIdRepository,我想进一步扩展它以满足项目特定的需要。班级的签名是 class BaseIdRepository[I <: BaseId, A <: WithId[I], T <: IdTable[I, A]] (

我正在为play2/slick2项目编写一个抽象的CRUD-DAO。为了方便地使用类型安全的主ID,我在slicks
MappedTo
&
ColumnBaseType
的基础上使用它作为额外的抽象和方便

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]
这对我来说太多余了。我能够从
T
提供
tableName
query
,在我自己的抽象DAO上给我以下签名

abstract class AbstractIdDao[I <: BaseId, A <: WithId[I], T <: IdTable[I, A]] 
  extends BaseIdRepository[I,A,T](TableQuery[T].baseTableRow.tableName, TableQuery[T])
这在没有运行时反射的情况下是可能的吗?如果仅通过运行时反射:如何在类定义中使用清单,以及在反应式应用程序中对性能的影响有多大

另外,由于我对这门语言相当陌生,并且是自己工作的:这在scala中是一个很好的实践吗

谢谢你的帮助。请随意批评我的问题和英语。当然,改进将提交给麒麟git回购

编辑:
实际上,
TableQuery[T].baseTableRow.tableName,TableQuery[T]
不起作用,因为错误的类类型是必需的,但找不到,IDEA表面上还可以,scalac不行。

至于你的第一个问题,我在使用Slick时也遇到过这个问题。但如果您仔细考虑一下,就会发现您无法在编译时执行此操作。这是因为需要此类型信息来指定类型参数之间的关系。如果不这样做,则可以在类型没有意义的情况下构造
BaseIdRepository
类,例如
IdTables
,其中表不表示投影。因为每个关系都需要名称,所以需要3个命名类型参数。如果省略第一个,则可以在不包含Id的投影的情况下构造IdRepository;如果省略第二个,则可能有一个没有ID列的表;如果省略第三个,则可以查询没有表和具有ID的投影组合的表。应用程序中可能没有定义会破坏这些规则的类型,但编译器不知道这一点。提供适当的类型信息是不可避免的

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

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


所以是的,你想要的是不可能的。Scala(和Slick)在编译时需要完整的信息,任何技巧都无法有效地绕过这一点。

有关
TableQuery[T].baseTableRow.tableName上错误的解释,请参见此其他答案。错误是在宏内部发出的,这可能是IntelliJ无法看到和检测它的原因。
abstract class AbstractIdDao[I <: BaseId, A <: WithId[I], T <: IdTable[I, A]] 
  extends BaseIdRepository[I,A,T](TableQuery[T].baseTableRow.tableName, TableQuery[T])
class UserDao extends AbstractIdDao[Users]