software - Usos de Null/Nothing/Unit en Scala
scala tutorial (7)
¿Tiene usos de Unit / Null / Nothing como algo más que un tipo de devolución?
Unit
se puede usar así:
def execute(code: => Unit):Unit = {
// do something before
code
// do something after
}
Esto le permite pasar un bloque de código arbitrario para ser ejecutado.
Null
se puede usar como un tipo inferior para cualquier valor que sea nulo. Un ejemplo es esto:
implicit def zeroNull[B >: Null] =
new Zero[B] { def apply = null }
Nothing
se usa en la definición de None
object None extends Option[Nothing]
Esto le permite asignar una None
a cualquier tipo de Option
porque Nothing
''extiende'' todo.
val x:Option[String] = None
Acabo de leer: http://oldfashionedsoftware.com/2008/08/20/a-post-about-nothing/
Por lo que yo entiendo, Null
es un rasgo y su única instancia es null
.
Cuando un método toma un argumento nulo, entonces solo podemos pasarle una referencia null
o null
directamente, pero no cualquier otra referencia, incluso si es nulo ( nullString: String = null
por ejemplo).
Me pregunto en qué casos usar este rasgo Null
podría ser útil. También está el rasgo de Nothing para el que realmente no veo más ejemplos.
Realmente no entiendo tampoco cuál es la diferencia entre usar Nothing y Unit como un tipo de devolución, ya que ambos no arrojan ningún resultado, ¿cómo saber cuál usar cuando tengo un método que realiza el registro, por ejemplo?
¿Tiene usos de Unit / Null / Nothing como algo más que un tipo de devolución?
Aquí hay un ejemplo de Nothing
from scala.predef
:
def ??? : Nothing = throw new NotImplementedError
En caso de que no estés familiarizado (¿y los motores de búsqueda no pueden buscar en él) ???
es la función de marcador de posición de Scala para todo lo que no se haya implementado aún. Al igual que TODO
de Kotlin.
Puede usar el mismo truco al crear objetos simulados: anule los métodos no utilizados con un método notUsed
personalizado. La ventaja de no usar ???
es que no obtendrás advertencias de compilación para cosas que nunca intentas implementar.
El artículo que cita puede ser engañoso. El tipo Null
está ahí para la compatibilidad con la máquina virtual Java y Java en particular.
Debemos considerar que Scala :
- está completamente orientado a objetos: cada valor es un objeto
- está fuertemente tipado: cada valor debe tener un tipo
- necesita manejar referencias
null
para acceder, por ejemplo, bibliotecas y códigos Java
por lo tanto, se hace necesario definir un tipo para el valor null
, que es el rasgo Null
, y tiene null
como su única instancia.
No hay nada especialmente útil en el tipo Null
menos que sea el sistema de tipos o que esté desarrollando en el compilador. En particular, no veo ninguna razón sensata para definir un parámetro de tipo Null
para un método, ya que no se puede pasar nada más que null
Nunca usé el tipo Null
, pero usas Unit
, donde usarías java use void
. Nothing
es un tipo especial, porque como Nathan ya mencionó, no puede haber ninguna instancia de Nothing
. Nothing
es lo que se llama tipo de fondo, lo que significa que es un subtipo de cualquier otro tipo. Este (y el parámetro de tipo contravariante) es la razón por la que puede anteponer cualquier valor a Nil
, que es una List[Nothing]
, y la lista será entonces de este tipo de elementos. None
también si de tipo Option[Nothing]
. Cada intento de acceder a los valores dentro de dicho contenedor generará una excepción, ya que es la única forma válida de regresar de un método de tipo Nothing
.
Solo usa Nothing si el método nunca regresa (lo que significa que no puede completarse normalmente al regresar, podría generar una excepción). Nada nunca se crea una instancia y está ahí para el beneficio del sistema de tipos (para citar a James Iry: "La razón por la que Scala tiene un tipo de fondo está ligada a su capacidad para expresar la varianza en los parámetros de tipo" ). Del artículo al que vinculó:
Otro uso de Nothing es como un tipo de devolución para métodos que nunca regresan. Tiene sentido si lo piensas. Si el tipo de devolución de un método es Nothing, y no existe absolutamente ninguna instancia de Nothing, entonces dicho método nunca debe volver.
Su método de registro devolvería la unidad. Hay una Unidad de valor para que pueda ser devuelta. De los documentos API :
La unidad es un subtipo de scala.AnyVal. Solo hay un valor de tipo Unidad, (), y no está representado por ningún objeto en el sistema de tiempo de ejecución subyacente. Un método con un tipo de retorno Unit es análogo a un método Java que se declara vacío.
si usa Nothing
, no hay cosas que hacer (incluya la consola de impresión) si hace algo, use el tipo de salida Unit
object Run extends App {
//def sayHello(): Nothing = println("hello?")
def sayHello(): Unit = println("hello?")
sayHello()
}
... entonces, ¿cómo usar Nothing
?
trait Option[E]
case class Some[E](value: E) extends Option[E]
case object None extends Option[Nothing]
Nada se usa a menudo implícitamente. En el código siguiente, val b: Boolean =
if (1 > 2) false
else throw new RuntimeException("error")
la cláusula else es de tipo Nothing , que es una subclase de Boolean (y cualquier otra AnyVal). Por lo tanto, toda la tarea es válida para el compilador, aunque la cláusula else realmente no devuelve nada.