Skip to content

Instantly share code, notes, and snippets.

@diversit
Created April 21, 2017 14:34
Show Gist options
  • Save diversit/c04b4b90199c1f7d4045b24ab6a6afe0 to your computer and use it in GitHub Desktop.
Save diversit/c04b4b90199c1f7d4045b24ab6a6afe0 to your computer and use it in GitHub Desktop.
Scala help to match an object with the argument type of another object
object TypeHelper {
import scala.reflect.runtime.universe.TypeTag
def getTypeTag[T : TypeTag](t: T): TypeTag[T] = implicitly[TypeTag[T]]
/**
* Checks if the object matches the type of the typed object.
*
* @param obj An object instance.
* @param typedObj A type object with a 'val argTypeTypeTag: TypeTag[_]' property.
* @return <code>true</code> when the object class and the type class are equal. Does not check sub/super types!
*/
def objectMatchesTypeOfTypedClass(obj: Any, typedObj: { val argTypeTypeTag: TypeTag[_] }): Boolean = {
// determine RuntimeClass of argument type
val tpe = typedObj.argTypeTypeTag.tpe
val argTypeRuntimeClass = typedObj.argTypeTypeTag.mirror.runtimeClass(tpe)
// determine RuntimeClass of object
val aRuntimeClass = ClassTag(obj.getClass).runtimeClass
// Compare both
argTypeRuntimeClass == aRuntimeClass
}
/**
* Checks if the object matches the type of the typed object.
* Note: this function is probably more efficient then the other one,
* but this function requires both TypeTag's to be present whereas
* the other function only needs one TypeTag.
*
* @param obj An object instance.
* @param typedObj A type object with at least 1 type argument.
* @return <code>true</code> when the object class and the type class are equal. Does not check sub/super types!
*/
def objectMatchesTypeOfTypedClass[A : TypeTag, B : TypeTag](obj: A, typedObj: B) = {
val objectType = getTypeTag(obj).tpe
val typedObjectType = getTypeTag(typedObj).tpe
if (typedObjectType.typeArgs.isEmpty) {
throw new Exception(s"Object '' is not typed")
}
// type argument of typed object
val typedObjectArgType = typedObjectType.typeArgs(0)
// compare type of object and of typed object
objectType =:= typedObjectArgType
}
}
--- TEST ---
package com.philips.flexc.api.protocol.flexc
import org.scalatest.{Matchers, WordSpec}
/**
* Testing [[TypeHelper]].
*/
class TypeHelperTest extends WordSpec with Matchers {
import TypeHelperTest._
"TypeTagHelper" when {
"matching object type with typed object type" should {
"succeed if type of object matches object type" in {
val obj = MyObject()
val typedObj = OtherTypedObject(obj)
val result = TypeHelper.objectMatchesTypeOfTypedClass(obj, typedObj)
result should be (true)
}
"succeed if type of object matches object type (2)" in {
val obj: MyTrait = MyObject()
val typedObj = MyTypedObject(MyObject())
val result = TypeHelper.objectMatchesTypeOfTypedClass(obj, typedObj)
result should be (true)
}
"fail if type of object matches object type" in {
{
val obj: MyTrait = MyOtherObject()
val typedObj = MyTypedObject(MyObject())
val result = TypeHelper.objectMatchesTypeOfTypedClass(obj, typedObj)
result should be(false)
}
{
val obj = MyOtherObject()
val typedObj = OtherTypedObject(MyObject())
val result = TypeHelper.objectMatchesTypeOfTypedClass(obj, typedObj)
result should be(false)
}
}
}
}
}
object TypeHelperTest {
trait MyTrait
case class MyObject() extends MyTrait
case class MyOtherObject() extends MyTrait
import scala.reflect.runtime.universe.TypeTag
case class MyTypedObject[T <: MyTrait : TypeTag](t: T) {
lazy val argTypeTypeTag = implicitly[TypeTag[T]]
}
case class OtherTypedObject[T <: MyTrait : TypeTag](t: T)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment