Pregunta

En Scala varianza se puede definir con los operadores de la varianza como + y - en el argumento de tipo genérico. Por ejemplo el tipo List es covariante en la biblioteca estándar.

class List[+A]

Así que una función con una lista de covarianza se puede definir como sigue:

def foo[A](list : List[A])

También varianza puede ser emulado con los límites genéricos. Así también podemos escribir este

def foo[A](list : List[_:< A])

Por supuesto, esto no tiene sentido, porque ya está list covariante. Pero el mismo truco se podía hacer por tipos que no son covariantes. (Como Stack). Por supuesto, también a nuevos tipos se podrían crear de pila (herencia de agregación) que es covariante.

Así que mis preguntas:

  1. Cuando debe ser Utilizar límites genéricos para la varianza? Y cuando debemos crear un nuevo tipo covariante?
  2. ¿Son los límites genéricos sólo es útil para la varianza, o pueden declarar más (conceptos del lenguaje).
  3. Si sólo son útiles para la varianza, son los límites a continuación, sólo por compatibilidad con Java?

THX de antemano:)

¿Fue útil?

Solución

Si un tipo es, naturalmente, covariantes o contravariantes se debe declarar que así sea. Sus usuarios se lo agradecerán. La varianza uso in situ es de hecho la mayoría de allí a causa de Java. Más precisamente, un tipo tal como Array[T <: Number] se trata como una taquigrafía para un tipo existencial:

ArrayBuffer[T] forSome { type T <: Number }

tipos existenciales tienen una sintaxis bastante voluminoso en Scala. En cierto modo es intencional, ya que no recomendamos que los usa mucho. ¿Cuándo se necesita un tipo existencial?

  1. Para escribir el análogo de un tipo Java con comodines, como List<? extends Number>.
  2. Para escribir el análogo de un tipo de prima Java, como List.

En Java, los tipos de primas y tipos de comodines no son exactamente lo mismo y tampoco es exactamente lo mismo que un tipo existencial (a pesar de que sabemos lo que no son, es bastante difícil de establecer con precisión lo que son). Pero son lo suficientemente cerca de los existenciales en la práctica, de manera que Scala se sale con la cartografía de ellos a este tipo de tipo.

Otros consejos

  1. Cuando se crea un nuevo tipo genérico, por ejemplo Foo [T], debe esforzarse para determinar si ese tipo es covariante, contravariant o invariante, y os lo Foo [+ T], Foo [-T] o Foo [T] respectivamente. Es cierto que esto puede ser un poco difícil. Sin embargo, se libera al usuario de Foo de tomar esa decisión cada vez que necesita usar un Foo utilizando límites genéricos. En resumen: prefiera declaración sitio de varianza sobre la llamada sitio de varianza cuando la varianza es una propiedad del tipo en sí.

Por cierto, la programación en el libro de Martin Scala Odersky, Lex cuchara y Bill Venners tiene algunas grandes seactions sobre la varianza. Véase el Capítulo 19 Tipo de parametrización.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top