user1187135
user1187135

Reputation:

How to match scala generic type with trait

This is the original method by passing in a DatabaseType.

trait DatabaseComponent

class Database {
  this: DatabaseComponent =>

}

object Database {
  def apply(dbType : DatabaseType): Unit ={
    val database = dbType match {
      case DatabaseType.H2 => new Database with H2Component {}
      case DatabaseType.MySQL => new Database with MySQLComponent {}
      case DatabaseType.PostgresSQL => new Database with PostgresSQLComponent {}
    }
  }
}

I want to, however, pass in the generic type and using typeOf(T) like in C#

private void Apply<T>(){
   switch(typeOf(T)){
     Something
   }
}

I am looking at this post How to match scala generic type?

But I am still not sure what this is doing.

1) Whats with the implicitly for this val string = implicitly[ClassTag[String]]

2) Why does T have to be subclass of ClassTag here implicitly[ClassTag[T]] match {

3) Should I be using ClassTag or TypeTag here?

Upvotes: 1

Views: 796

Answers (2)

user1187135
user1187135

Reputation:

To partially supplement the answer by @uberwach

Unlike C#, JVM has type erasure that erases all type date at runtime. So typeOf is not possible in Scala. You cannot create a new instance of type T at runtime.

Type erasure: Java vs C#

Upvotes: 0

uberwach
uberwach

Reputation: 1109

1 and 2 kinda have the same answer, you may want to read about type classes. Here the type class is ClassTag[T]. Essentially, a type class is an interface that can be "attached" to any type via an implementation called instance of the type class. In Scala instances of type classes are looked for in implicit scope, so while you could implement several different instances for a type there may never be more than one implementation (or it is ambiguous). If you write something like

def method[T : TypeClass](p1, p2, ...) 

you force to have an instance of TypeClass for type T in the scope when method is called. Note that this is equivalent to

def method[T](p1, p2, ...)(implicit val ev: TypeClass[T]) ...

So you have actually a hidden parameter that you could give explicitly(!)

implicitly[X] is actually a method that obtains any implicit value of type X living in the current scope. You can actually implement it yourself:

def yourImplicitly[T](implicit val ev: T) : T = ev

There are tons of applications for type classes as this is kind of a fruitful abstraction. You may want to read up about the "extension problem", as type-classes are a solution to the extension problem for FP languages.

Actually it might be the case that you could make your DatabaseComponent a type class itself.

  1. I am not quite sure about the answer here, you may want to check http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html. If I understand your problem correctly, then class tags may suffice (and are imho easier to use).

Upvotes: 1

Related Questions