Created
April 21, 2017 14:34
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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