How to define generic type in Scala?
scala, slick
Solution
When you do `TableQuery[T]` you are in fact calling `TableQuery.apply`, which is actually a macro.
The body of this macro tries to instantiate `T`, but in your case T has become an (unknown) type parameter that the compiler does not know how to instantiate. The problem is similar to trying to compile this:
def instantiate[T]: T = new T
// Does not compile ("class type required but T found")
The net effect is that `TableQuery.apply` can only be used on concrete types.
You could work around that using a type class to capture the call to `TableQuery.apply` (at the point where the concrete type is known) along with an implicit macro to provide an instance of this type class. Then you would have something like:
abstract class TableUtils[T <: Table[A] : TableQueryBuilder, A] {
val tableQuery = BuildTableQuery[T]
}
Where `TableQueryBuilder` is the type class and `BuildTableQuery` is an alternate version of `TableQuery.apply` that will forward to the `TableQueryBuilder` instance to perform the actual instantiation.
I've added an implementation as part of another answer here.
It will be much easier (if less convenient) to just declare `tableQuery` as an abstract value and define it in every concrete derived class of `TableUtils`:
abstract class TableUtils[T <: Table[A] , A] {
val tableQuery: TableQuery[T, T#TableElementType]
// define here your helper methods operating on `tableQuery`
}
object Coolers extends TableUtils[Coolers, Cooler] {
val tableQuery = TableQuery[Coolers]
}
Problem
In Slick 2, we can map tables like this: ``` case class Cooler(id: Option[Int], minTemp: Option[Double], maxTemp: Option[Double]) /** * Define table "cooler". */ class Coolers(tag: Tag) extends Table[Cooler](tag, "cooler") { def id = column[Int]("id", O.PrimaryKey, O.AutoInc) def minTemp = column[Double]("min_temp", O.Nullable) def maxTemp = column[Double]("max_temp", O.Nullable) def * = (id.?, minTemp.?, maxTemp.?) <> (Cooler.tupled, Cooler.unapply _) } object Coolers { val tableQuery = TableQuery[Coolers] } ``` because I have a lot of tables, I want to define generic methods for them, like `find`, `delete`, `update` so I have to define these methods in a super class from where to extend my objects (`object Coolers extends TableUtils[Coolers, Cooler]`). In order to define those methods, I need `tableQuery` to move out of my object in this super class, so I tried it like: ``` abstract class TableUtils[T <: Table[A] , A] { val tableQuery = TableQuery[T] } ``` but I receive an error on `tableQuery` definition: `class type required but T found` Does anybody know what I am doing wrong?