¿Por qué Void no es el tipo inferior en Java?
Si el único elemento del tipo Void
es null
, y null
es un elemento de cada tipo de referencia en Java, ¿por qué no se considera a Void
un subtipo de cada tipo de referencia? Aparte de razones heredadas, ¿existen razones por las cuales Void
no debería ser considerado el tipo inferior en Java?
Nota: Estoy buscando una justificación de diseño (si existe), no solo “porque lo dice el JLS”.
Posible caso de uso: colecciones vacías
Un caso de uso común para el tipo inferior es tipificar una lista vacía. Consideremos las siguientes dos firmas de método, dadas las clases no relacionadas A
y B
.
float processAs(List<? extends A> as) { ... }
float processBs(List<? extends B> bs) { ... }
Observa que he hecho que los parámetros de lista sean ‘covariantes’ usando un comodín. Ahora, para alguna lista List<C> cs
donde C
es cualquier subtipo de A
, aún puedo llamar a processAs(cs)
(análogamente para processBs
). Supongamos ahora que tenemos una lista vacía List<...> empty = Collections.emptyList();
. Dependiendo del tipo que rellene en los puntos suspensivos, puedo llamar a processAs
cuando es un subtipo de A
o llamar a processBs
cuando es un subtipo de B
, pero no ambos. Sin embargo, no puede ocurrir nada inseguro si pudiera pasarla a ambos. Si Void
se considerara el tipo inferior, podríamos tipificarlo como List<Void>
y podría llamar a processAs(empty)
y processBs(empty)
sin ningún problema.
Esto funcionaría de manera similar al tipo Nothing en Scala, donde las listas también se consideran covariantes.
Un poco de contexto
Estoy escribiendo un traductor de código desde un lenguaje llamado Nouga (que aún no se ha lanzado) a Java. En Nouga, hay un tipo inferior llamado nothing
. El tipo Void
parecía la traducción más adecuada para eso. Aunque puedo solucionar la mala traducción de la relación de subtipo utilizando coerciones, me dio curiosidad si existen razones por las cuales Void
no debería considerarse el tipo inferior.
Posiblemente relacionado: https://stackoverflow.com/q/14219529/3083982 Pero esta pregunta parece ser más acerca de una confusión entre covarianza y contravarianza (es decir, el OP utiliza void
como si fuera el tipo superior, no el tipo inferior).
davy.ai
La razón por la cual
Void
no es considerado un subtipo de todos los tipos de referencia, a pesar de que su único elemento esnull
, se debe al hecho de que esto rompería la relación de subtipos, que se define en términos de compatibilidad de asignación. Específicamente, siVoid
fuera un subtipo de todos los tipos de referencia, entonces cualquier expresión del tiponull
sería asignable a cualquier tipo de referencia, lo cual claramente no es el caso. Además, esto también introduciría ambigüedades en la resolución de métodos, ya que cualquier método con un tipo de retorno deVoid
sería sobreescrito por cualquier método con un tipo de retorno que sea un tipo de referencia.En cuanto a si
Void
debería considerarse el tipo inferior en Java, aparte de las consideraciones heredadas, hay casos de uso potenciales para tratarlo como tal. Por ejemplo, se podría usar para tipificar colecciones vacías, como se describe en la sección anterior. Sin embargo, esto requeriría un cambio en el sistema de tipos de Java y probablemente introduciría problemas de compatibilidad. Además, los beneficios de dicho cambio pueden no superar los costos, ya que ya existen soluciones alternativas disponibles para lograr efectos similares.