Estoy tomando el curso de Martin Odersky sobre programación funcional con scala, y por ahora he aprendido dos cosas que juntas no tienen sentido:
- Scala no admite herencia múltiple
Nothing
es un subtipo de cualquier otro tipo
Estas dos declaraciones no pueden vivir juntas, entonces, ¿cómo se hace esto exactamente? y cuál es exactamente el significado de "subtipo de cualquier otro tipo"
Editar 1
En la API de Scala , Nothing
se define como abstract final class Nothing extends Any
... entonces, ¿cómo puede extender otras clases?
programming-languages
scala
vainolo
fuente
fuente
Nothing
sea una subclase de todas las demás clases. Dice que es un subtipo de cualquier otro tipo .Respuestas:
¡El subtipo y la herencia son dos cosas diferentes!
Nothing
no extiende todo, es un subtipo , solo se extiendeAny
.La especificación [§3.5.2] tiene un caso especial que rige la relación de subtipo de
Nothing
:Donde
<:
básicamente significa "es un subtipo de".En cuanto a cómo se hace esto: no lo sabemos, es magia del compilador y un detalle de implementación.
Muy a menudo un lenguaje hace cosas que usted como programador no puede hacer. Como contrapartida de
Nothing
: Todo en Scala hereda deAny
, todo exceptoAny
. ¿Por qué noAny
hereda de algo? No puedes hacer eso. ¿Por qué Scala puede hacer eso? Bueno, porque Scala estableció las reglas, no tú.Nothing
ser un subtipo de todo es solo otra instancia de esto.fuente
null
ser asignable a un campo de todo tipo en Java. ¿Por qué es eso posible? ¿Esnull
una instancia de cada clase? No, es posible porque el compilador lo dice. Período.extends
en Java, y no como componer ) lo haces para subtipar después de todo.Cuando dice que Scala no admite la herencia múltiple, se refiere a heredar la implementación de un método varias veces. Por supuesto, puede implementar múltiples interfaces / rasgos en una clase, e incluso pueden definir el mismo método, pero no obtiene un conflicto entre las diferentes implementaciones debido a la linealización de rasgos.
En general, si tiene una clase
C1
con un métodof()
y una claseC2
también con un métodof()
, la herencia múltiple significa que de alguna manera puede heredar ambas implementaciones def()
. Esto puede conducir a varios problemas, que Scala resuelve al solo dejarle heredar de una sola clase y en el caso de múltiples rasgos seleccionando una implementación basada en el orden de los rasgos.En cuanto a las
Nothing
cosas, son realmente simples, porque nada tiene atributos o métodos definidos. Por lo tanto, no puede tener ningún conflicto de herencia. Pero supongo que la mayor parte de su sorpresa proviene de una comprensión diferente de la herencia múltiple.Una vez que comprenda que la linealización de rasgos elimina efectivamente cualquier ambigüedad de la herencia, y que no nos referimos a heredar de múltiples rasgos como herencia múltiple debido a eso, entonces debería estar bien.
En cuanto a cómo se realiza esto: el compilador finalmente es responsable de esto. Consulte la sección de especificación del lenguaje Scala 3.5.2 conformidad, que entre otras propiedades incluye:
O, en otras palabras, si desea implementar un compilador correctamente, debe manejarse
Nothing
como un subtipo de todo por especificación. Por razones obvias,Nothing
no está definido para extenderse desde todas las clases cargadas en el sistema, pero la relevancia de definirNothing
como subtipo está limitada a todos los lugares, donde el subtipo es relevante.Un punto importante aquí es que no existe una instancia de tipo
Nothing
, por lo tanto, su tratamiento se limita estrictamente a la verificación de tipo, que está en el ámbito del compilador.fuente