En programación orientada a objetos , el operador de navegación segura (también conocido como operador de encadenamiento opcional , operador de llamada segura , operador condicional nulo , operador de propagación nula ) es un operador binario que devuelve nulo si su primer argumento es nulo; de lo contrario, realiza una operación de desreferenciación según lo especificado por el segundo argumento (normalmente un acceso a un miembro de objeto, un índice de matriz o una invocación lambda).
Se utiliza para evitar comprobaciones y asignaciones nulas explícitas secuenciales y reemplazarlas con encadenamiento de métodos/propiedades. En lenguajes de programación donde el operador de navegación (por ejemplo, ".") conduce a un error si se aplica a un objeto nulo, el operador de navegación segura detiene la evaluación de una cadena de métodos/campos y devuelve nulo como valor de la expresión de la cadena. Fue utilizado por primera vez por Groovy 1.0 en 2007 [1] y actualmente es compatible con lenguajes como C# , [2] Swift , [3] TypeScript , [4] Ruby , [5] Kotlin , [6] Rust , [7] JavaScript , [8] y otros. Actualmente no existe una convención de nomenclatura común para este operador, pero el operador de navegación segura es el término más utilizado.
La principal ventaja de utilizar este operador es que evita la pirámide de la perdición . En lugar de escribir múltiples s anidados if, los programadores pueden utilizar el encadenamiento habitual, pero añadir símbolos de interrogación antes de los puntos (u otros caracteres utilizados para el encadenamiento).
Si bien el operador de navegación segura y el operador de coalescencia nula son ambos operadores que reconocen valores nulos , son operativamente diferentes.
Ejemplos
Ápex
Ejemplos de operadores de navegación segura: [9]
a [ x ]?. aMethod ( ). aField // Se evalúa como nulo si a[x] == null a [ x ] ?. aMethod () ?. aField // Devuelve nulo si a[x].aMethod() se evalúa como nulo String profileUrl = user.getProfileUrl ( ) ?. toExternalForm ( ); return [ SELECT Name FROM Account WHERE Id = : accId ] ?. Name ;
DO#
C# 6.0 y versiones posteriores tienen ?., el operador de acceso a miembros condicional nulo (que también se denomina operador Elvis por Microsoft y no debe confundirse con el uso general del término operador Elvis , cuyo equivalente en C# es ??, el operador de coalescencia nula ) y ?[], el operador de acceso a elementos condicional nulo , que realiza una llamada segura frente a nulos de un descriptor de acceso get de indexador . Si el tipo del resultado del acceso a miembros es un tipo de valor , el tipo del resultado de un acceso condicional nulo de ese miembro es una versión que acepta valores nulos de ese tipo de valor . [10]
El siguiente ejemplo recupera el nombre del autor del primer artículo en una matriz de artículos (siempre que cada artículo tenga un Authormiembro y que cada autor tenga un Namemiembro), y da como resultado nullsi la matriz es null, si su primer elemento es null, si el Authormiembro de ese artículo es nullo si el Namemiembro de ese autor es null. Tenga en cuenta que IndexOutOfRangeExceptionse sigue lanzando un si la matriz no es nula sino que está vacía (es decir, tiene longitud cero).
var nombre = articulos ? [ 0 ] ? .Autor ? .Nombre ;
Para llamar a una lambda se requiere callback?.Invoke(), ya que no hay invocación condicional nula ( callback?()no está permitido).
var resultado = devolución de llamada ?. Invocar ( args );
Clojure
Clojure no tiene operadores verdaderos en el sentido en que otros lenguajes lo utilizan, pero como es interoperable con Java y tiene que realizar navegación de objetos cuando lo hace, la macro some->[11] se puede usar para realizar una navegación segura.
( algunos-> artículo .autor .nombre )
Script de café
Operador existencial: [12]
código postal = lotería . ganador del sorteo ? (). dirección ? . código postal
Cristal
Crystal admite el trymétodo de navegación segura [13]
nombre = artículo . try & . autor . try & . nombre
Dardo
Operador de acceso condicional a miembros: [14]
var nombre = articulo ? . autor ? . nombre
Dios
Operador de invocación segura nula: [15]
var nombre = articulo ? .autor ? .nombre
El operador de invocación seguro contra valores nulos no es necesario para los atributos de clase declarados como propiedades de Gosu:
clase Foo { var _bar : Cadena como Bar }
var foo : Foo = nulo
// lo siguiente se evaluará como nulo y no devolverá una NullPointerException
var bar = foo . Bar
Genial
Operador de navegación segura y operador de índice seguro: [1] [16]
def nombre = articulo ?. autores ?[ 0 ]. nombre
JavaScript
Agregado en ECMAScript 2020, el operador de encadenamiento opcional proporciona una forma de simplificar el acceso a valores a través de objetos conectados cuando es posible que una referencia o función no esté definida o sea nula . [17] Los principales navegadores de escritorio lo han admitido desde 2020, y la mayoría de los navegadores móviles agregaron soporte en 2024. [18]
const nombre = artículo ? . autores ? .[ 0 ] ? . nombre const resultado = devolución de llamada ? .()
Cortocircuita toda la cadena de llamadas en su lado derecho: en el siguiente ejemplo, no se "accede" a bar .
nulo ? . foo . bar
Kotlin
Operador de llamada segura: [6]
val nombre = articulo ? .autor ? .nombre
Objetivo-C
La sintaxis de navegación normal se puede utilizar en la mayoría de los casos sin tener en cuenta los valores NULL, ya que los mensajes subyacentes, cuando se envían a NULL, se descartan sin efectos negativos.
NSString * nombre = artículo . autor [ 0 ]. nombre ;
Perl 5
Perl 5 no tiene este tipo de operador, pero se aceptó una propuesta de inclusión con la siguiente sintaxis: [19]
mi $nombre = $articulo ? -> autor ? -> nombre ;
PHP
El operador seguro nulo fue aceptado para PHP 8: [20]
$nombre = $artículo ?-> autor ?-> nombre ;
Raku (Perl 6)
Llamada al método seguro: [21]
mi $nombre = $articulo .? autor .? nombre ;
Rubí
Ruby admite el &.operador de navegación segura (también conocido como operador solitario ) desde la versión 2.3.0: [5]
nombre = artículo &. autor &. nombre
Óxido
Rust proporciona un ?operador [7] que puede parecer un operador de navegación seguro. Sin embargo, una diferencia clave es que cuando ?encuentra un Nonevalor, no evalúa como None. En cambio, se comporta como una returndeclaración, lo que hace que la función o el cierre que lo encierra devuelvan inmediatamente None.
Los Optionmétodos map()y and_then()se pueden utilizar para una navegación segura, pero esta opción es más detallada que un operador de navegación segura:
fn print_author ( article : Option < Article > ) { println! ( " Autor : { } " , article.and_then ( | y | y.author ) .map ( | z | z.name ) .unwrap_or ( " Desconocido " .to_owned ( ) ) ) ; }
Una implementación que use ?no imprimirá nada (ni siquiera "Autor:") si articlees Noneo article.unwrap().authores None. En cuanto ?ve un None, la función retorna.
fn try_print_author ( article : Option < Article > ) -> Option < () > {
println! ( "Autor: {}" , article ? .author ? .name ) ; Some (() ) }
Escala
El operador seguro para valores nulos en Scala lo proporciona la biblioteca Dsl.scala. [22] [23]
val nombre = articulo . ? . autor . ? . nombre : @ ?
La @ ?anotación se puede utilizar para indicar un valor que acepta valores nulos.
clase de caso Árbol ( izquierda : Árbol @ ? = null , derecha : Árbol @ ? = null , valor : Cadena @ ? = null )
val root : Árbol @ ? = Árbol ( izquierda = Árbol ( izquierda = Árbol ( valor = "izquierda-izquierda" ), derecha = Árbol ( valor = "izquierda-derecha" ) , derecha = Árbol ( valor = " derecha" )
Lo normal .en Scala no es seguro frente a valores nulos cuando se ejecuta un método sobre un nullvalor.
Se debe generar una [ NullPointerException ] mediante { root . right . left . right . value // ¡root.right.left es nulo! }
La excepción se puede evitar utilizando ?el operador en el valor que acepta valores nulos:
raíz . ? . derecha . ? . izquierda . ? . el valor debe ser ( nulo )
La expresión completa es nullsi ?se realiza una de ellas sobre un nullvalor.
El límite de un nulloperador seguro ?es la expresión envolvente más cercana cuyo tipo está anotado como @ ?.
( "Hola " + ( "mundo " + raíz . ? . derecha . ? . izquierda . ? . valor )) debería ser ( "Hola mundo null" ) ( "Hola " + (( "mundo " + raíz . ? . derecha . ? . izquierda . ? . valor . ? ): @ ? )) debería ser ( "Hola null" ) (( "Hola " + ( "mundo " + raíz . ? . derecha . ? . izquierda . ? . valor . ? )): @ ? ) debería ser ( null )
Rápido
Operador de encadenamiento opcional, operador de subíndice [3] y llamada:
deje que nombre = artículo ?. autores ?[ 0 ]. nombre
deje que resultado = protocolVar ?. opcionalRequisito ?()
Mecanografiado
El operador de encadenamiento opcional se incluyó en la versión 3.7 de Typescript: [4]
sea x = foo ? . bar ? .[ 0 ] ? . baz ();
Visual Basic .NET
Visual Basic 14 y versiones posteriores tienen el ?.( operador de acceso a miembros condicional nulo ) y ?()el ( operador de índice condicional nulo ), similares a C#. Tienen el mismo comportamiento que los operadores equivalentes en C#. [24]
La siguiente declaración se comporta de manera idéntica al ejemplo de C# anterior.
Dim name = artículos ? ( 0 ) ? . Autor ? . Nombre
Véase también
Referencias
- ^ "Operadores condicionales nulos (C# y Visual Basic)" . Consultado el 28 de enero de 2016 .
- ^ ab "Encadenamiento opcional" . Consultado el 28 de enero de 2016 .
- ^ ab "Typescript 3.7" . Consultado el 6 de noviembre de 2019 .
- ^ ab "Lanzamiento de Ruby 2.3.0" . Consultado el 28 de enero de 2016 .
- ^ ab "Seguridad nula" . Consultado el 28 de enero de 2016 .
- ^ ab "El operador de signo de interrogación, ?" . Consultado el 4 de octubre de 2021 .
- ^ "MDN - encadenamiento opcional en JavaScript".
- ^ "Notas de la versión de Salesforce Winter 21". Salesforce . Consultado el 13 de octubre de 2020 .
- ^ "Operadores de acceso a miembros (referencia de C#)". Microsoft Docs . Microsoft . Consultado el 29 de agosto de 2019 .
- ^ "Guía de macros de subprocesamiento" . Consultado el 7 de junio de 2019 .
- ^ "El Operador Existencial" . Consultado el 15 de junio de 2017 .
- ^ "API de Crystal: Objeto#try".
- ^ "Otros operadores". Un recorrido por el lenguaje Dart . Consultado el 8 de enero de 2020 .
- ^ "El lenguaje de programación Gosu" . Consultado el 18 de diciembre de 2018 .
- ^ "8.5. Operador de índice seguro" . Consultado el 25 de septiembre de 2020 .
- ^ "Encadenamiento opcional en ECMAScript 2020".
- ^ "Compatibilidad del navegador con encadenamiento opcional en JavaScript".
- ^ "PPC 21 - Encadenamiento opcional". GitHub .
- ^ "PHP: rfc:nullsafe_operator". wiki.php.net . Consultado el 1 de octubre de 2020 .
- ^ "Operadores de Raku" . Consultado el 16 de septiembre de 2022 .
- ^ Un marco para crear lenguajes específicos de dominio integrados en Scala: ThoughtWorksInc/Dsl.scala, ThoughtWorks Inc., 2019-06-03 , consultado el 2019-06-03
- ^ "NullSafe: el operador ? seguro para valores nulos con sabor a Kotlin/Groovy ahora está disponible en Scala". Usuarios de Scala . 2018-09-12 . Consultado el 2019-06-03 .
- ^ "Operadores condicionales nulos ?. y ?() (Visual Basic)". Microsoft Docs . Microsoft . Consultado el 29 de agosto de 2019 .
Enlaces externos
- PEP 505, discusión sobre la posibilidad de operadores de navegación seguros para Python
