I am quite new to Scala programming. Besides Scala, I have never learned functional programming. With that said, I am currently trying to figure out a good way to define traits, classes, etc, on a project using slick.
My idea was to have a trait having the methods to be implemented on the child classes, and some would be implemented on the parent class itself. I found a way that works but I have no idea why. Not sure if this problem is related to how Slick or Scala works.
I was using a construction like:
trait CompanyDAO extends BaseDao[Company]{
self: DBProfile =>
But this give the following type mismatch error:
[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]
But, if I use
self: DBProfile with BaseDao[Company] =>
Then the compilation works (BTW, got the solution from another post)
So, my questions:
1) Why using self-types toTable assignment works while extending the trait do not? How scala interprets the type of toTable in both scenarios?
2) Is there a way to adapt the "trait CompanyDAO extends BaseDao" to solve the error?
Thank you in advance.
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: some other things I have been trying
Extending BaseDao, 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)
Tried also using self-type and it gave me the same error.