2017-09-16 82 views
0

我对Scala编程颇为陌生。除了Scala之外,我从来没有学过函数式编程。这就是说,我目前正在试图找出一个很好的方法来在使用光滑的项目上定义特征,类等。在父特征上使用泛型TableQuery类型

我的想法是有一个特性,在子类上实现方法,有些会在父类本身上实现。我找到了一种方法,但我不知道为什么。不知道这个问题与Slick或Scala的工作方式有关。

我使用的是建筑,如:

trait CompanyDAO extends BaseDao[Company]{ 
self: DBProfile => 

但是,这给下面的类型不匹配错误:

[error] found : slick.lifted.TableQuery[CompanyDAO.this.CompanyTable] [error] required: slick.lifted.TableQuery[CompanyDAO.this.profile.api.Table[Company]] [error] (which expands to) slick.lifted.TableQuery[CompanyDAO.this.profile.Table[Company]] [error] Note: CompanyDAO.this.CompanyTable <: CompanyDAO.this.profile.api.Table[Company], but class TableQuery is invariant in type E. [error] You may wish to define E as +E instead. (SLS 4.5) [error] override def toTable = TableQuery[CompanyTable]

但是,如果我用

self: DBProfile with BaseDao[Company] => 

然后汇编作品(顺便说一句,从another post得到解决方案)

所以,我的问题:

1)为什么使用自我类型toTable分配工作,而扩大特质不? scala如何在两种情况下解释toTable的类型?

2)有没有一种方法来适应“特性CompanyDAO扩展BaseDao”来解决错误?

预先感谢您。

import scala.concurrent.Future 
import slick.basic.DatabaseConfig 
import slick.jdbc.JdbcProfile 

trait DBConfiguration { 
    lazy val config = DatabaseConfig.forConfig[JdbcProfile]("mytrade") 
} 

trait DBProfile { 
    val config: DatabaseConfig[JdbcProfile] 
    val db: JdbcProfile#Backend#Database = config.db 
    val profile : JdbcProfile = config.profile 
} 

trait BaseDao[T <: Any] { 
    self: DBProfile => 

    import profile.api._ 
    import slick.lifted.TableQuery 

    def toTable():TableQuery[Table[T]] 
    def findAll():Future[Seq[T]] = db.run(toTable.result) 
} 

case class Company(name: String, code: Int) 

// If I use the construction like the comment below, it will fail 
//trait CompanyDAO extends BaseDao[Company]{ 
    //self: DBProfile => 

trait CompanyDAO { 
    self: DBProfile with BaseDao[Company] => 
    //import from DBProfile trait 
    import profile.api._ 

    class CompanyTable(tag: Tag) extends Table[Company](tag, "COMPANY") { 

    import slick.ast.BaseTypedType 
    import slick.jdbc.JdbcType 

    def name = column[String]("name") 
    def code = column[Int]("code") 

    def * = (name, code) <> (Company.tupled, Company.unapply) 
    } 

    override def toTable = TableQuery[CompanyTable] 
} 

编辑:一些其他的事情,我一直在努力

扩展BaseDao,如果我改变的toTable的声明:

def toTable[S <: TableQuery[Table[_]]]():S 

类型不匹配会消失,但我现在收到:

test.scala:27: dead code following this construct [error] def findAll():Future[Seq[T]] = db.run(toTable.result)

试过还用自我型a nd它给了我同样的错误。

+0

1)https:// stackoverflow。com/questions/2224932 /特质差异 - 继承和自我类型注释 2)https://stackoverflow.com/questions/1990948/what-is-the-difference-between-self-types-和特质子类 3)https://softwareengineering.stackexchange.com/questions/219038/what-is-the-difference-between-self-types-and-trait-inheritance-in-scala –

回答

0

If I change the declaration of toTable to:

def toTable[S <: TableQuery[Table[_]]]():S

The type mismatch goes away but I receive now:

test.scala:27: dead code following this construct [error] def findAll():Future[Seq[T]] = db.run(toTable.result) 

Any ideas why is this happening?

我无法重现您的特定编译错误。

但是,当我更改线路

def toTable():TableQuery[Table[T]] 

def toTable[S <: TableQuery[Table[_]]]():S 

我编译错误

Error:(24, 51) value result is not a member of Nothing 
    def findAll():Future[Seq[T]] = db.run(toTable.result) 

这是因为类型参数S被推断为Nothing

您不提供实施方法toTableNothing <: TableQuery[Table[_]]

+0

谢谢你的参考,真的很有帮助。仅供参考,我使用Scala 2.12.1和Slick 3.2.0。我不明白的是为什么toTable():TableQuery [Table [T]]与自我类型一起工作,如果我使用继承,则不起作用。 scala如何在每种情况下解释这个变量的类型,逻辑是什么? –