Je suis relativement nouveau dans la programmation Scala. En dehors de Scala, je n'ai jamais appris la programmation fonctionnelle. Cela dit, j'essaie actuellement de trouver un bon moyen de définir les traits, les classes, etc., sur un projet utilisant Slick. Mon idée était d'avoir un trait ayant les méthodes à implémenter sur les classes enfant, et certaines seraient implémentées sur la classe parente elle-même. J'ai trouvé un moyen qui fonctionne mais je ne sais pas pourquoi. Je ne sais pas si ce problème est lié au fonctionnement de Slick ou Scala.Utilisation du type TableQuery générique sur le trait parent
j'utilisais une construction comme:
trait CompanyDAO extends BaseDao[Company]{
self: DBProfile =>
Mais cela donne l'erreur d'incompatibilité de type:
[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]
Mais, si j'utilise
self: DBProfile with BaseDao[Company] =>
Ensuite, les travaux de compilation (BTW, a obtenu la solution de another post)
Alors, mes questions:
1) Pourquoi l'utilisation de self-types toTable fonctionne tout en n'étendant pas le trait? Comment scala interprète le type de toTable dans les deux scénarios?
2) Existe-t-il un moyen d'adapter le "trait CompanyDAO extends BaseDao" pour résoudre l'erreur?
Merci d'avance.
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]
}
EDIT: d'autres choses que j'ai essayé
Extension BaseDao, Si je change la déclaration de Totable à:
def toTable[S <: TableQuery[Table[_]]]():S
L'incompatibilité de type va loin, mais je reçois maintenant :
test.scala:27: dead code following this construct [error] def findAll():Future[Seq[T]] = db.run(toTable.result)
Essayé également en utilisant un auto-type ça m'a donné la même erreur.
1) https: // stackoverflow.com/questions/2224932/différence-entre-trait-héritage-et-auto-type-annotation 2) https://stackoverflow.com/questions/1990948/what-is-the-difference-between-self-types- et-trait-sous-classes 3) https://softwareengineering.stackexchange.com/questions/219038/what-is-the-difference-between-self-types-and-trait-inheritance-in-scala –