variable una referencias que programacion poo orientada objetos objeto instancias instanciar instancia entre diferencia denomina clases clase scala instanceof scala-2.10

scala - referencias - ¿Cómo saber si un objeto es una instancia del tipo de TypeTag?



referencias a objetos e instancias en poo (4)

En su caso específico, si realmente necesita migrar el código existente y mantener el mismo comportamiento, desea ClassTag . Usar TypeTag es más preciso, pero exactamente por eso, algunos códigos se comportarán de manera diferente, por lo que (en general) debe tener cuidado.

Si realmente desea TypeTag , podemos hacerlo incluso mejor que la sintaxis anterior; el efecto en el sitio de la llamada es el mismo que omitiendo U

Alternativas recomendadas

Usando el proxenetismo

Con la respuesta de Eugene, uno tiene que escribir ambos tipos, mientras que es deseable deducir el tipo de that . Dada una lista de parámetros de tipo, se especifica todo o ninguno; El tipo de curry podría ayudar, pero parece más simple simplemente pinchar el método. Utilicemos para estas clases implícitas, también nuevas en 2.10, para definir nuestra solución en solo 3 líneas .

import scala.reflect.runtime.universe._ implicit class MyInstanceOf[U: TypeTag](that: U) { def myIsInstanceOf[T: TypeTag] = typeOf[U] <:< typeOf[T] }

De hecho, argumentaría que algo como esto, con un nombre mejor (por ejemplo, stat_isInstanceOf ), podría incluso pertenecer a Predef.

Use ejemplos:

//Support testing (copied from above) class A class B extends A class C //Examples (new B).myIsInstanceOf[A] //true (new B).myIsInstanceOf[C] //false //Examples which could not work with erasure/isInstanceOf/classTag. List(new B).myIsInstanceOf[List[A]] //true List(new B).myIsInstanceOf[List[C]] //false //Set is invariant: Set(new B).myIsInstanceOf[Set[A]] //false Set(new B).myIsInstanceOf[Set[B]] //true //Function1[T, U] is contravariant in T: ((a: B) => 0).myIsInstanceOf[A => Int] //false ((a: A) => 0).myIsInstanceOf[A => Int] //true ((a: A) => 0).myIsInstanceOf[B => Int] //true

Una sintaxis más compatible.

Si el proxenetismo es un problema porque cambia la sintaxis de invocación y usted tiene un código existente, podemos probar el tipo de currying (más complicado de usar) de la siguiente manera, de modo que solo se deba pasar un parámetro de tipo explícitamente, como en su definición anterior con Any :

trait InstanceOfFun[T] { def apply[U: TypeTag](that: U)(implicit t: TypeTag[T]): Boolean } def myIsInstanceOf[T] = new InstanceOfFun[T] { def apply[U: TypeTag](that: U)(implicit t: TypeTag[T]) = typeOf[U] <:< typeOf[T] } myIsInstanceOf[List[A]](List(new B)) //true

Si desea aprender a escribir dicho código usted mismo, puede estar interesado en la discusión de las variaciones que se muestran a continuación.

Otras variaciones y intentos fallidos.

La definición anterior se puede hacer más compacta con tipos estructurales:

scala> def myIsInstanceOf[T] = new { //[T: TypeTag] does not give the expected invocation syntax def apply[U: TypeTag](that: U)(implicit t: TypeTag[T]) = typeOf[U] <:< typeOf[T] } myIsInstanceOf: [T]=> Object{def apply[U](that: U)(implicit evidence$1: reflect.runtime.universe.TypeTag[U],implicit t: reflect.runtime.universe.TypeTag[T]): Boolean}

Sin embargo, el uso de tipos estructurales no siempre es una buena idea, como advierte -feature:

scala> myIsInstanceOf[List[A]](List(new B)) <console>:14: warning: reflective access of structural type member method apply should be enabled by making the implicit value language.reflectiveCalls visible. This can be achieved by adding the import clause ''import language.reflectiveCalls'' or by setting the compiler option -language:reflectiveCalls. See the Scala docs for value scala.language.reflectiveCalls for a discussion why the feature should be explicitly enabled. myIsInstanceOf[List[A]](List(new B)) ^ res3: Boolean = true

El problema es la desaceleración debida a la reflexión, necesaria para implementar tipos estructurales. Resolverlo es fácil, solo alarga un poco el código, como se vio anteriormente.

Una trampa que tuve que evitar

En el código anterior, escribo [T] lugar de [T: TypeTag] , mi primer intento. Es interesante por qué falla. Para entender eso, eche un vistazo:

scala> def myIsInstanceOf[T: TypeTag] = new { | def apply[U: TypeTag](that: U) = | typeOf[U] <:< typeOf[T] | } myIsInstanceOf: [T](implicit evidence$1: reflect.runtime.universe.TypeTag[T])Object{def apply[U](that: U)(implicit evidence$2: reflect.runtime.universe.TypeTag[U]): Boolean}

Si observa detenidamente el tipo del valor de retorno, puede ver que es implicit TypeTag[T] => U => implicit TypeTag[U] (en notación pseudo-Scala). Cuando pase un argumento, Scala pensará que es para la primera lista de parámetros, la implícita:

scala> myIsInstanceOf[List[A]](List(new B)) <console>:19: error: type mismatch; found : List[B] required: reflect.runtime.universe.TypeTag[List[A]] myIsInstanceOf[List[A]](List(new B)) ^

Una punta

Lo último y lo menos, una sugerencia que podría o no interesarte: en este intento, estás pasando TypeTag [T] dos veces; por lo tanto, debes eliminar : TypeTag después de [T

def myIsInstanceOf[T: TypeTag, U: TypeTag](tag: TypeTag[T], that: U) = myInstanceToTpe(that) stat_<:< tag.tpe

Tengo una función que puede saber si un objeto es una instancia del tipo de Manifest . Me gustaría TypeTag a una versión de TypeTag . La antigua función es la siguiente:

def myIsInstanceOf[T: Manifest](that: Any) = implicitly[Manifest[T]].erasure.isInstance(that)

He estado experimentando con TypeTags y ahora tengo esta versión de TypeTag:

// Involved definitions def myInstanceToTpe[T: TypeTag](x: T) = typeOf[T] def myIsInstanceOf[T: TypeTag, U: TypeTag](tag: TypeTag[T], that: U) = myInstanceToTpe(that) stat_<:< tag.tpe // Some invocation examples class A class B extends A class C myIsInstanceOf(typeTag[A], new A) /* true */ myIsInstanceOf(typeTag[A], new B) /* true */ myIsInstanceOf(typeTag[A], new C) /* false */

¿Hay alguna mejor manera de lograr esta tarea? ¿Se puede omitir la U parametrizada, utilizando un Any lugar (tal como se hace en la función antigua)?


Si es suficiente con el uso de chequeos de subtipos en tipos borrados, haga lo que Travis Brown sugirió en el comentario anterior:

def myIsInstanceOf[T: ClassTag](that: Any) = classTag[T].runtimeClass.isInstance(that)

De lo contrario, debe deletrear explícitamente el tipo U , para que scalac capture su tipo en una etiqueta de tipo:

def myIsInstanceOf[T: TypeTag, U: TypeTag] = typeOf[U] <:< typeOf[T]



Utilicé las sugerencias anteriores para llegar a lo siguiente. La retroalimentación es bienvenida.

/* Attempting to cast Any to a Type of T, using TypeTag http://.com/questions/11628379/how-to-know-if-an-object-is-an-instance-of-a-typetags-type */ protected def toOptInstance[T: ClassTag](any: Any) = classTag[T].runtimeClass.isInstance(any) match { case true => Try(any.asInstanceOf[T]).toOption case false => /* Allow only primitive casting */ if (classTag[T].runtimeClass.isPrimitive) any match { case u: Unit => castIfCaonical[T](u, "void") case z: Boolean => castIfCaonical[T](z, "boolean") case b: Byte => castIfCaonical[T](b, "byte") case c: Char => castIfCaonical[T](c, "char") case s: Short => castIfCaonical[T](s, "short") case i: Int => castIfCaonical[T](i, "int") case j: Long => castIfCaonical[T](j, "long") case f: Float => castIfCaonical[T](f, "float") case d: Double => castIfCaonical[T](d, "double") case _ => None } else None } protected def castIfCaonical[T: ClassTag](value: AnyVal, canonicalName: String): Option[T] ={ val trueName = classTag[T].runtimeClass.getCanonicalName if ( trueName == canonicalName) Try(value.asInstanceOf[T]).toOption else None }