software renault examples scala

scala - renault - Cuándo usar la opción



scala vs java (4)

Cuando se trata de programación funcional en Scala, Option es mucho más preferible que null ya que es de tipo seguro y juega bien con otras construcciones en el paradigma funcional.

Especialmente, puede escribir fácilmente código idiomático usando funciones de alto orden en Option . Esta hoja de referencia de opciones de Scala es una lectura útil sobre el tema.

Aprendo Scala por algún tiempo y no puedo entender claramente el uso de la Opción. Me ayuda a evitar las comprobaciones nulas cuando encadeno funciones (según los docs ). Eso está claro para mí :)

A continuación, veo que la opción puede ser un tipo de indicador para el desarrollador de que aquí es posible un valor nulo y debe manejarse. ¿Es verdad? Si es así, ¿debo usar la opción donde sea posible? Por ejemplo

class Racer { val car = new Car() }

Tengo una clase de Racer y estoy seguro de que el campo del coche no puede ser nulo (porque es constante y obtiene un valor cuando creo la instancia de Racer). No hay necesidad de opción aquí.

class Racer { var car = new Car() }

Aquí lo hago para que el coche pueda cambiar. Y es posible que alguien le asigne nulo al auto. ¿Debo usar la opción aquí? Si es así, me doy cuenta de que todos los campos de mi clase son candidatos para la opción. Y mi código se ve así

class Racer { var car: Option[Car] = None var currentRace: Option[Race] = None var team: Option[Team] = None ... }

¿Se ve bien? Para mí parece una especie de sobreuso de opción.

def foo(): Result = { if( something ) new Result() else null }

Tengo un método que puede devolver nulo. ¿Debo devolver la opción en su lugar? ¿Debo hacerlo siempre si es posible que un método devuelva nulo?

Cualquier pensamiento al respecto sería útil. ¡Gracias por adelantado!

Mi pregunta es similar a la opción Por qué, pero creo que no es lo mismo. Es más sobre cuándo, no por qué. :)


Debes evitar el null tanto como sea posible en Scala. Realmente solo existe para la interoperabilidad con Java. Entonces, en lugar de null , use Option siempre que sea posible que una función o método pueda devolver "ningún valor", o cuando sea lógicamente válido para una variable miembro que no tenga "ningún valor".

Con respecto a tu ejemplo de Racer : ¿Es realmente válido un Racer si no tiene un car , una currentRace y un team ? Si no es así, entonces no debería hacer esas opciones de variables miembro. No solo haga las opciones porque teóricamente es posible asignarlas a null ; hágalo solo si, lógicamente, lo considera un objeto Racer válido si alguna de esas variables miembro no tiene valor.

En otras palabras, es mejor fingir que null no existe. El uso de null en el código Scala es un olor de código.

def foo(): Option[Result] = if (something) Some(new Result()) else None

Tenga en cuenta que la Option tiene muchos métodos útiles para trabajar.

val opt = foo() // You can use pattern matching opt match { case Some(result) => println("The result is: " + result) case None => println("There was no result!") } // Or use for example foreach opt foreach { result => println("The result is: " + result) }

Además, si desea programar en el estilo funcional, debe evitar los datos mutables tanto como sea posible, lo que significa: evite el uso de var , use val lugar, use colecciones inmutables y haga que sus propias clases sean lo más inmutables posible.


La idea detrás de Options es deshacerse de null , así que sí, debes usarlas en lugar de devolver " null o un valor". Por eso también, si desea modelar campos opcionales (relación 0..1 con otros objetos), usar Option es definitivamente una buena cosa.

El pequeño inconveniente es que hace que la declaración de clase con un montón de campos opcionales sea un poco detallada, como mencionó.

Una cosa más, en Scala, se recomienda utilizar "objetos inmutables", por lo que en su ejemplo, los campos deben tener algunos val . ;)


Si bien Option puede hacer que su definición de clase tenga un aspecto detallado, la alternativa es no saber cuándo necesita probar si una variable está definida. Creo que en su ejemplo, si su clase fuera inmutable (todos los campos eran val s), no necesitaría tantas Option .

Para su método foo , si devuelve un valor nulo, debe documentarlo y el cliente debe leer esa documentación. Luego el cliente escribirá un montón de código como:

val result = foo(x) if (result != null) { println(result) }

Si, en cambio, define foo para devolver una Option[Result] , el sistema de tipos obliga al cliente a manejar la posibilidad de un resultado no definido. También tienen todo el poder de las clases de colecciones.

result foreach println

Una ventaja adicional de usar el método de colecciones con una Option lugar de probar el null es que si su método se extiende a una colección de elementos múltiples (como una List ), es posible que no necesite cambiar su código en absoluto. Por ejemplo, inicialmente puede suponer que su Racer solo puede tener una única tripulación, por lo que define val crew: Option[Crew] y puede probar si la tripulación es mayor de 30 con crew.forall(_.age > 30).getOrElse(false) . Ahora, si ha cambiado la definición a val crew: List[Crew] su código anterior aún compilaría y ahora verificará si todos los miembros de su tripulación tienen más de 30.

A veces necesita tratar con null porque las bibliotecas que está utilizando pueden devolverlo. Por ejemplo, cuando obtiene un recurso, puede obtener un resultado null . Afortunadamente, es fácil envolver los resultados de manera defensiva para que se transformen en una opción.

val resource = Option(this.getClass.getResource("foo"))

Si getResource devolvió un null , el resource es igual a None y, de lo contrario, se trata de un Some[URL] . ¡Guay!

Desafortunadamente, es probable que la Option tenga algo de sobrecarga porque implica la creación de un objeto adicional. Sin embargo, esa sobrecarga es mínima en comparación con una excepción de puntero nulo!