stringtranslate.com

Sobrecarga de operadores

En programación informática , la sobrecarga de operadores , a veces denominada polimorfismo ad hoc de operadores , es un caso específico de polimorfismo , en el que distintos operadores tienen distintas implementaciones según sus argumentos. La sobrecarga de operadores suele definirse por un lenguaje de programación , un programador o ambos.

Razón fundamental

La sobrecarga de operadores es un azúcar sintáctico y se utiliza porque permite programar utilizando una notación más cercana al dominio de destino [1] y permite que los tipos definidos por el usuario tengan un nivel de soporte sintáctico similar al de los tipos integrados en un lenguaje. Es común, por ejemplo, en la computación científica, donde permite manipular representaciones computacionales de objetos matemáticos con la misma sintaxis que en el papel.

La sobrecarga de operadores no altera el poder expresivo de un lenguaje (con funciones), ya que se puede emular mediante llamadas a funciones. Por ejemplo, considere variables y ade algún tipo definido por el usuario, como matrices :bc

a + b * c

En un lenguaje que admite la sobrecarga de operadores, y con la suposición habitual de que el operador '*' tiene mayor precedencia que el operador '+', esta es una forma concisa de escribir:

Add(a, Multiply(b, c))

Sin embargo, la sintaxis anterior refleja un uso matemático común.

Ejemplos

En este caso, el operador de suma se sobrecarga para permitir la suma en un tipo definido por el usuario Timeen C++ :

Operador de tiempo + ( const Tiempo & lhs , const Tiempo & rhs ) { Tiempo temp = lhs ; temp . segundos += rhs . segundos ; temp . minutos += temp . segundos / 60 ; temp . segundos %= 60 ; temp . minutos += rhs . minutos ; temp . horas += temp . minutos / 60 ; temp . minutos %= 60 ; temp . horas += rhs . horas ; devolver temp ; }                                      

La suma es una operación binaria , lo que significa que tiene dos operandos . En C++, los argumentos que se pasan son los operandos y el tempobjeto es el valor devuelto.

La operación también podría definirse como un método de clase, reemplazándola lhspor el thisargumento oculto; sin embargo, esto obliga a que el operando izquierdo sea del tipo Time:

// La "const" justo antes de la llave de apertura significa que |this| no se modifica. Time Time :: operator + ( const Time & rhs ) const { Time temp = * this ; // |this| no debe modificarse, por lo que debe hacer una copia. temp . seconds += rhs . seconds ; temp . minutes += temp . seconds / 60 ; temp . seconds %= 60 ; temp . minutes += rhs . minutes ; temp . hours += temp . minutes / 60 ; temp . minutes %= 60 ; temp . hours += rhs . hours ; return temp ; }                                     

Tenga en cuenta que un operador unario definido como un método de clase no recibiría ningún argumento aparente (solo funciona desde this):

bool Tiempo :: operador ! () const { return horas == 0 && minutos == 0 && segundos == 0 ; }               

El operador menor que (<) a menudo se sobrecarga para ordenar una estructura o clase:

clase Par { público : bool operador < ( const Par & p ) const { si ( x_ == p.x_ ) { devolver y_ < p.y_ ; } devolver x_ < p.x_ ; }                         privado : int x_ ; int y_ ; };    

Al igual que en los ejemplos anteriores, en el último ejemplo la sobrecarga de operadores se realiza dentro de la clase. En C++, después de sobrecargar el operador menor que (<), se pueden utilizar funciones de ordenación estándar para ordenar algunas clases.

Críticas

La sobrecarga de operadores ha sido criticada a menudo [2] porque permite a los programadores reasignar la semántica de los operadores dependiendo de los tipos de sus operandos. Por ejemplo, el uso del <<operador en C++ desplaza los bits en la variable que quedan por bits si y son de un tipo entero, pero si es un flujo de salida, entonces el código anterior intentará escribir a en el flujo. Debido a que la sobrecarga de operadores permite al programador original cambiar la semántica habitual de un operador y tomar por sorpresa a los programadores posteriores, se considera una buena práctica utilizar la sobrecarga de operadores con cuidado (los creadores de Java decidieron no utilizar esta característica, [3] aunque no necesariamente por esta razón).a << bababab

Otro problema, más sutil, con los operadores es que ciertas reglas de las matemáticas pueden esperarse erróneamente o asumirse involuntariamente. Por ejemplo, la conmutatividad de + (es decir, que a + b == b + a) no siempre se aplica; un ejemplo de esto ocurre cuando los operandos son cadenas, ya que + se sobrecarga comúnmente para realizar una concatenación de cadenas (es decir, "bird" + "song"produce "birdsong", mientras que "song" + "bird"produce "songbird"). Un contraargumento típico [ cita requerida ] a este argumento proviene directamente de las matemáticas: Si bien + es conmutativo en números enteros (y más generalmente en cualquier número complejo), no es conmutativo para otros "tipos" de variables. En la práctica, + ni siquiera es siempre asociativo , por ejemplo con valores de punto flotante debido a errores de redondeo. Otro ejemplo: en matemáticas, la multiplicación es conmutativa para números reales y complejos, pero no es conmutativa en la multiplicación de matrices .

Catalogar

Se realiza una clasificación de algunos lenguajes de programación comunes según si sus operadores son sobrecargables por el programador y si los operadores están limitados a un conjunto predefinido.

Cronología de la sobrecarga de operadores

Década de 1960

La especificación ALGOL 68 permitía la sobrecarga de operadores. [44]

Extracto de la especificación del lenguaje ALGOL 68 (página 177) donde se definen los operadores sobrecargados ¬, =, ≠ y abs :

10.2.2. Operaciones con operandos booleanosa) op ∨ = ( bool a, b) bool :( a | verdadero | b );b) op ∧ = ( bool a, b) bool : ( a | b | falso );c) op ¬ = ( bool a) bool : ( a | falso | verdadero );d) op = = ( bool a, b) bool :( a∧b ) ∨ ( ¬b∧¬a );e) op ≠ = ( bool a, b) bool : ¬(a=b);f) op  abs = ( bool a) int : ( a | 1 | 0 );

Tenga en cuenta que no se necesita ninguna declaración especial para sobrecargar un operador y el programador tiene libertad para crear nuevos operadores. En el caso de los operadores diádicos, se puede establecer su prioridad en comparación con otros operadores:

 prioridad  máxima = 9;  op  máx = ( int a, b) int : ( a>b | a | b ); op  ++ = ( ref  int a ) int : ( a +:= 1 );

Década de 1980

Ada admite la sobrecarga de operadores desde su inicio, con la publicación del estándar de lenguaje Ada 83. Sin embargo, los diseñadores del lenguaje decidieron evitar la definición de nuevos operadores. Solo se pueden sobrecargar los operadores existentes en el lenguaje, definiendo nuevas funciones con identificadores como "+", "*", "&", etc. Las revisiones posteriores del lenguaje (en 1995 y 2005) mantienen la restricción a la sobrecarga de operadores existentes.

En C++ , la sobrecarga de operadores es más refinada que en ALGOL 68. [ 45]

Década de 1990

Los diseñadores del lenguaje Java en Sun Microsystems decidieron omitir la sobrecarga. [46] [47] [48]

Python permite la sobrecarga de operadores a través de la implementación de métodos con nombres especiales. [49] Por ejemplo, el operador de suma (+) se puede sobrecargar implementando el método obj.__add__(self, other).

Ruby permite la sobrecarga de operadores como azúcar sintáctica para llamadas a métodos simples.

Lua permite la sobrecarga de operadores como azúcar sintáctica para llamadas a métodos con la característica adicional de que si el primer operando no define ese operador, se utilizará el método para el segundo operando.

Década de 2000

Microsoft agregó la sobrecarga de operadores a C# en 2001 y a Visual Basic .NET en 2003.

Scala trata a todos los operadores como métodos y por lo tanto permite la sobrecarga de operadores por proxy.

En Raku , la definición de todos los operadores se delega en funciones léxicas y, por lo tanto, mediante definiciones de funciones, se pueden sobrecargar operadores o agregar operadores nuevos. Por ejemplo, la función definida en el código fuente de Rakudo para incrementar un objeto Date con "+" es:

multi  infijo:<+> ( Fecha:D  $d , Int:D  $x ) { Fecha . nuevo-desde-días ( $d . día + $x )}

Dado que se utilizó "multi", la función se agrega a la lista de candidatos de multidispatch , y "+" solo se sobrecarga en el caso en que se cumplan las restricciones de tipo en la firma de la función. Si bien la capacidad de sobrecarga incluye + , * , >= , el sufijo y el término i , etc., también permite la sobrecarga de varios operadores de llaves: " [ x, y ] ", "x [ y ] ", "x { y } " y "x ( y ) ".

Kotlin ha admitido la sobrecarga de operadores desde su creación.

Véase también

Referencias

  1. ^ Stroustrup, Bjarne . "Sobrecarga de operadores". Preguntas frecuentes sobre C++ . Archivado desde el original el 14 de agosto de 2011 . Consultado el 27 de agosto de 2020 .
  2. ^ Fisher, Charles N. (2008). "Problemas de sobrecarga" (PDF) . Universidad de Wisconsin-Madison .
  3. ^ "No más sobrecarga de operadores". El entorno del lenguaje Java . Oracle Corporation .
  4. ^ Se pueden agregar operadores completamente nuevos.
  5. ^ Las funciones binarias con un nombre simbólico pueden llamarse infijas.
  6. ^ "Predicado op/3".
  7. ^ Hunt, John (6 de diciembre de 2012). Smalltalk y orientación a objetos: una introducción. Springer Science & Business Media. ISBN 978-1-4471-0961-7.
  8. ^ "Bertrand Meyer: Mecanismos básicos del lenguaje Eiffel". se.ethz.ch . Consultado el 7 de abril de 2021 .
  9. ^ "Funciones de los operadores en F90". www.mathcs.emory.edu . Consultado el 7 de abril de 2021 .
  10. ^ Introducido en Fortran 90.
  11. ^ "3. Referencia del lenguaje — Documentación de Futhark 0.19.0". futhark.readthedocs.io . Consultado el 10 de octubre de 2020 .
  12. ^ Smith, Chris (9 de octubre de 2012). Programación F# 3.0: una guía completa para escribir código simple para resolver problemas complejos. O'Reilly Media, Inc. ISBN 978-1-4493-2604-3.
  13. ^ Escriba clases en lugar de sobrecargar.
  14. ^ "Guía de io". iolanguage.org . Consultado el 7 de abril de 2021 .
  15. ^ "Operadores".
  16. ^ "Operadores - R en pocas palabras, 2.ª edición [Libro]". www.oreilly.com . Consultado el 7 de abril de 2021 .
  17. ^ "Creación de operadores".
  18. ^ "Operadores". Recorrido por la Scala .
  19. ^ "Manual de Seed7: Definición de sintaxis estructurada". seed7.sourceforge.net . Consultado el 29 de septiembre de 2020 .
  20. ^ "Swift: Operadores avanzados".
  21. ^ "¿Por qué Go no admite la sobrecarga de métodos y operadores?" . Consultado el 4 de septiembre de 2011 .
  22. ^ "Introducción". freepascal.org . Consultado el 30 de septiembre de 2020 .
  23. ^ "Sobrecargas de operadores" . Consultado el 28 de septiembre de 2018 .
  24. ^ "6.6 Sobrecarga de operadores". Manual de referencia de Ada anotado .
  25. ^ Drayton, Peter; Albahari, Ben; Neward, Ted (2003). C# en pocas palabras. O'Reilly Media, Inc. ISBN 978-0-596-00526-9.
  26. ^ "Sobrecarga de operadores en C++".
  27. ^ "Eclipse Ceylon: polimorfismo de operadores". ceylon-lang.org . Consultado el 7 de abril de 2021 .
  28. ^ "Sobrecarga de operadores - Lenguaje de programación D". dlang.org . Consultado el 10 de octubre de 2020 .
  29. ^ "Un recorrido por el lenguaje Dart". dart.dev . Consultado el 30 de septiembre de 2020 .
  30. ^ "Sobrecarga del operador". bourabai.kz . Consultado el 7 de abril de 2021 .
  31. ^ "El lenguaje de programación Apache Groovy - Operadores". groovy-lang.org . Consultado el 30 de septiembre de 2020 .
  32. ^ "Sobrecarga del operador". Manifold . Consultado el 7 de junio de 2020 .
  33. ^ "Sobrecarga de operadores". Kotlin . Consultado el 24 de junio de 2018 .
  34. ^ "Tutorial de metamétodos". Wiki de usuarios de Lua .
  35. ^ "Implementación de operadores para su clase" . Consultado el 1 de octubre de 2013 .
  36. ^ "Sobrecarga de operadores". Manual de Free Pascal . Consultado el 1 de diciembre de 2014 .
  37. ^ "Sobrecarga del operador". Manual de Delphi . Consultado el 1 de diciembre de 2014 .
  38. ^ "Métodos mágicos de PHP que anulan propiedades de clase". Archivado desde el original el 4 de marzo de 2016 . Consultado el 7 de abril de 2015 .
  39. ^ Orwant, Jon (4 de noviembre de 2002). Ciencias de la computación y programación en Perl: lo mejor de The Perl Journal. O'Reilly Media, Inc., págs. 347–. ISBN 978-0-596-00310-4.
  40. ^ "3. Modelo de datos". Referencia del lenguaje Python .
  41. ^ "Métodos". Preguntas frecuentes oficiales de Ruby .
  42. ^ "Sobrecarga del operador". Rust By Example .
  43. ^ "Cómo: Definir un operador (Visual Basic)".
  44. ^ = Barry J. Mailloux "Informe sobre el lenguaje algorítmico ALGOL 68, Sección 10.2.2". Agosto de 1968. Consultado el 1 de abril de 2007 . {{cite web}}: Verificar |url=valor ( ayuda )
  45. ^ Stroustrup, Bjarne . "Una historia de C++: 1979−1991" (PDF) . p. 12 . Consultado el 1 de abril de 2007 .
  46. ^ "Pregunta 6.9 de preguntas frecuentes: ¿Por qué no hay sobrecarga de operadores?". Lista de preguntas frecuentes de comp.lang.java .
  47. ^ "java.sun.com". Archivado desde el original el 7 de marzo de 2009. Consultado el 26 de marzo de 2009 .
  48. ^ Holzner, Steven (2001). C++: Black Book . Scottsdale, Arizona: Coriolis Group. pág. 387. ISBN. 1-57610-777-9Una de las mejores características de C++ OOP es que puedes sobrecargar operadores para manejar objetos de tus clases (no puedes hacer esto en otros lenguajes centrados en OOP, como Java) .
  49. ^ "3. Modelo de datos, nombres de métodos especiales". Referencia del lenguaje Python .