If I understand correctly, what you want is to extend MyBase by simply defining M and T , but without explicitly creating an instance of TableQuery in each derived class.
Using reflection is actually not an option, since you usually use TableQuery.apply for this (as in val query = TableQuery[MyTable] ), and this is implemented with a macro, so you have a "runtime and compilation" problem.
If you absolutely need MyBase be a sign (as opposed to a class), I don't see any viable solution. However, if you can turn MyBase into a class and , turn M and T into type parameters (instead of abstract types), that is, at least one solution. Since I hinted at another related question ( How to define a generic type in Scala? ), You can define a type class (say TableQueryBuilder ) to capture the call to TableQuery.apply (at the point where the particular type is known) along with an implicit macro (say TableQueryBuilder.builderForTable ) to provide an instance of this type. Then you can define a method (say TableQueryBuilder.build ) to actually create an instance of TableQuery that simply delegates the job to the type class.
// NOTE: tested with scala 2.11.0 & slick 3.0.0 import scala.reflect.macros.Context import scala.language.experimental.macros object TableQueryBuilderMacro { def createBuilderImpl[T<:AbstractTable[_]:c.WeakTypeTag](c: Context) = { import c.universe._ val T = weakTypeOf[T] q"""new TableQueryBuilder[$T]{ def apply(): TableQuery[$T] = { TableQuery[$T] } }""" } } trait TableQueryBuilder[T<:AbstractTable[_]] { def apply(): TableQuery[T] } object TableQueryBuilder { implicit def builderForTable[T<:AbstractTable[_]]: TableQueryBuilder[T] = macro TableQueryBuilderMacro.createBuilderImpl[T] def build[T<:AbstractTable[_]:TableQueryBuilder](): TableQuery[T] = implicitly[TableQueryBuilder[T]].apply() }
The net effect is that you no longer need to know a specific value of type T to be able to instantiate TableQuery[T] , provided that you have an implicit instance of TableQueryBuilder[T] in scope. In other words, you can transfer the need to know a specific value of T until you really know it.
MyBase (now a class) can be implemented as follows:
class MyBase[M, T <: Table[M] : TableQueryBuilder] { lazy val query: TableQuery[T] = TableQueryBuilder.build[T] }
And you can extend it without having to call TableQuery.apply :
class Coffees(tag: Tag) extends Table[(String, Double)](tag, "COFFEES") { def name = column[String]("COF_NAME") def price = column[Double]("PRICE") def * = (name, price) } class Derived extends MyBase[(String, Double), Coffees] // That it!
What happens here is that in the Derived constructor, the implicit value for TableQueryBuilder[Coffees] implicitly passed to the MyBase constructor.
The reason you can't apply this template if MyBase was a MyBase is pretty mundane: MyBase constructors can't have parameters, let alone implicit parameters, so there would be no implicit way to pass an instance of TableQueryBuilder .