La sobrecarga de operadores en C ++ es considerada por muchos como una mala cosa (tm), y es un error que no se repite en lenguajes más nuevos. Ciertamente, fue una característica que se eliminó específicamente al diseñar Java.
Ahora que he empezado a leer sobre Scala, encuentro que tiene lo que se parece mucho a la sobrecarga del operador (aunque técnicamente no tiene sobrecarga del operador porque no tiene operadores, solo funciones). Sin embargo, no parece ser cualitativamente diferente a la sobrecarga del operador en C ++, donde, según recuerdo, los operadores se definen como funciones especiales.
Entonces, mi pregunta es ¿qué hace que la idea de definir "+" en Scala sea una mejor idea que en C ++?
c++
scala
operator-overloading
skaffman
fuente
fuente
Respuestas:
C ++ hereda verdaderos operadores azules de C. Con eso quiero decir que el "+" en 6 + 4 es muy especial. No puede, por ejemplo, obtener un puntero a esa función +.
Scala, por otro lado, no tiene operadores de esa manera. Simplemente tiene una gran flexibilidad para definir nombres de métodos más un poco de precedencia incorporada para símbolos que no son palabras. Así que técnicamente Scala no tiene sobrecarga del operador.
Como quiera llamarlo, la sobrecarga del operador no es inherentemente mala, incluso en C ++. El problema es cuando los malos programadores lo abusan. Pero, francamente, soy de la opinión de que eliminar la capacidad de los programadores de abusar de la sobrecarga del operador no pone una gota en el balde de arreglar todo lo que los programadores pueden abusar. La verdadera respuesta es la tutoría. http://james-iry.blogspot.com/2009/03/operator-overloading-ad-absurdum.html
Sin embargo, existen diferencias entre la sobrecarga del operador de C ++ y la denominación de métodos flexibles de Scala que, en mi humilde opinión, hacen que Scala sea menos abusivo y más abusivo.
En C ++, la única forma de obtener la notación en corrección es utilizando operadores. De lo contrario, debe usar object.message (argumento) o puntero-> messsage (argumento) o función (argumento1, argumento2). Entonces, si desea un cierto estilo DSLish para su código, entonces hay presión para usar operadores.
En Scala puede obtener notación infija con cualquier mensaje enviado. "argumento de mensaje de objeto" está perfectamente bien, lo que significa que no necesita usar símbolos que no sean palabras solo para obtener la notación infija.
La sobrecarga del operador C ++ se limita esencialmente a los operadores C. Combinado con la limitación de que solo se pueden usar infix los operadores que presionan a las personas para que intenten mapear una amplia gama de conceptos no relacionados en relativamente pocos símbolos como "+" y ">>"
Scala permite una amplia gama de símbolos válidos que no son palabras como nombres de métodos. Por ejemplo, tengo un DSL Prolog-ish incrustado donde puedes escribir
Los símbolos: -,!,? Y & se definen como métodos comunes. Solo en C ++ sería válido, por lo que un intento de mapear este DSL en C ++ requeriría algunos símbolos que ya evocan conceptos muy diferentes.
Por supuesto, esto también abre Scala a otro tipo de abuso. En Scala puede nombrar un método $! & ^% Si lo desea.
Para otros lenguajes que, como Scala, son flexibles en el uso de nombres de funciones y métodos que no son de palabras, consulte Smalltalk donde, como Scala, cada "operador" es solo otro método y Haskell que permite al programador definir la precedencia y la fijación de nombres flexibles funciones
fuente
int main() {return (3).operator+(5);}
resultados enerror: request for member ‘operator+’ in ‘3’, which is of non-class type ‘int’
Solo por los ignorantes. Es absolutamente necesario en un lenguaje como C ++, y es notable que otros lenguajes que comenzaron con una visión "purista", lo hayan agregado una vez que sus diseñadores descubrieron lo necesario que es.
fuente
La sobrecarga del operador nunca se pensó universalmente como una mala idea en C ++, solo se pensó que el abuso de la sobrecarga del operador era una mala idea. Uno realmente no necesita la sobrecarga del operador en un idioma ya que de todos modos se pueden simular con llamadas a funciones más detalladas. Evitar la sobrecarga de operadores en Java hizo que la implementación y especificación de Java fuera un poco más simple y obligó a los programadores a no abusar de los operadores. Ha habido cierto debate en la comunidad Java sobre la introducción de la sobrecarga del operador.
Las ventajas y desventajas de la sobrecarga del operador en Scala son las mismas que en C ++: puede escribir un código más natural si usa la sobrecarga del operador de manera adecuada, y un código más críptico y ofuscado si no lo hace.
FYI: Los operadores no se definen como funciones especiales en C ++, se comportan como cualquier otra función, aunque existen algunas diferencias en la búsqueda de nombres, si necesitan ser funciones miembro y el hecho de que se pueden llamar de dos maneras: 1 ) sintaxis del operador, y 2) sintaxis del operador-función-id.
fuente
add(2, multiply(5, 3))
?Este artículo, " El legado positivo de C ++ y Java ", responde a su pregunta directamente.
Java erróneamente (según el autor) omitió la sobrecarga del operador porque era complicado en C ++, pero olvidó por qué (o no se dio cuenta de que no se aplicaba a Java).
Afortunadamente, los lenguajes de nivel superior como Scala ofrecen opciones a los desarrolladores, mientras se ejecutan en la misma JVM.
fuente
No hay nada malo con la sobrecarga del operador. De hecho, hay algo malo en no tener una sobrecarga del operador para los tipos numéricos. (Eche un vistazo a algunos códigos Java que usan BigInteger y BigDecimal).
Sin embargo, C ++ tiene la tradición de abusar de la función. Un ejemplo citado a menudo es que los operadores de desplazamiento de bits están sobrecargados para hacer E / S.
fuente
=
lugar de<<
y>>
en los primeros días de C ++, pero tuvo problemas ya que no tenía la prioridad de operador correcta (es decir, busca argumentos a la izquierda o derecha primero). Así que sus manos estaban un poco atadas sobre lo que podía usar.En general no es algo malo.
Nuevos lenguajes como C # también tienen sobrecarga del operador.
Es el abuso de la sobrecarga del operador lo que es malo.
Pero también hay problemas con la sobrecarga del operador como se define en C ++. Debido a que los operadores sobrecargados son simplemente azúcar sintáctica para las llamadas a métodos, se comportan igual que los métodos. Por otro lado, los operadores integrados normales no se comportan como los métodos. Estas inconsistencias pueden causar problemas.
De la parte superior de mi cabeza operadores
||
y&&
.Las versiones integradas de estos son operadores de acceso directo. Esto no es cierto para las versiones sobrecargadas y ha causado algunos problemas.
El hecho de que + - * / todos devuelven el mismo tipo en el que operan (después de la promoción del operador)
Las versiones sobrecargadas pueden devolver cualquier cosa (Aquí es donde se establece el abuso, si sus operadores comienzan a devolver algún tipo de árbitro que el usuario no esperaba las cosas van cuesta abajo).
fuente
La sobrecarga del operador no es algo que realmente "necesite" muy a menudo, pero cuando usa Java, si llega a un punto en el que realmente lo necesita, tendrá ganas de arrancarse las uñas para tener una excusa para dejar de escribir. .
¿Ese código que acabas de encontrar se desborda mucho? Sí, vas a tener que volver a escribir todo para que funcione con BigInteger. No hay nada más frustrante que tener que reinventar la rueda solo para cambiar el tipo de variable.
fuente
Guy Steele argumentó que la sobrecarga del operador también debería estar en Java, en su discurso principal "Cultivando un lenguaje": hay un video y una transcripción del mismo, y es realmente un discurso increíble. Te preguntarás de qué está hablando durante las primeras páginas, pero si sigues leyendo, verás el punto y lograrás la iluminación. Y el hecho mismo de que pudiera pronunciar ese discurso también es sorprendente.
Al mismo tiempo, esta charla inspiró mucha investigación fundamental, probablemente incluyendo a Scala, es uno de esos documentos que todos deberían leer para trabajar en el campo.
Volviendo al punto, sus ejemplos son principalmente sobre clases numéricas (como BigInteger y algunas cosas más extrañas), pero eso no es esencial.
Sin embargo, es cierto que el mal uso de la sobrecarga del operador puede conducir a resultados terribles, y que incluso los usos adecuados pueden complicar las cosas, si intenta leer el código sin estudiar un poco las bibliotecas que utiliza. ¿Pero es una buena idea? OTOH, ¿no deberían estas bibliotecas tratar de incluir una hoja de trucos para los operadores?
fuente
Creo que CADA respuesta se perdió esto. En C ++ puede sobrecargar a los operadores todo lo que quiera, pero no puede afectar la precedencia con la que se evalúan. Scala no tiene este problema, IIRC.
En cuanto a que es una mala idea, además de los problemas de precedencia, la gente tiene significados realmente tontos para los operadores, y rara vez ayuda a la legibilidad. Las bibliotecas Scala son especialmente malas para esto, símbolos tontos que debes memorizar cada vez, con los mantenedores de la biblioteca metiendo la cabeza en la arena diciendo: 'solo necesitas aprenderlo una vez'. Genial, ahora necesito aprender la sintaxis críptica de un autor "inteligente" * la cantidad de bibliotecas que me interesa usar. No sería tan malo si existiera una convención de SIEMPRE de suministrar una versión alfabetizada de los operadores.
fuente
La sobrecarga del operador no fue una invención de C ++: vino de Algol IIRC e incluso Gosling no afirma que sea una mala idea en general.
fuente
Lo único que se sabe mal en C ++ es la falta de la capacidad de sobrecargar [] = como un operador separado. Esto podría ser difícil de implementar en un compilador de C ++ por lo que probablemente no sea una razón obvia pero valga la pena.
fuente
Como las otras respuestas han señalado; La sobrecarga del operador en sí no es necesariamente mala. Lo que es malo cuando se usa de manera que hace que el código resultante no sea obvio. En general, cuando los usa, debe hacer que hagan lo menos sorprendente (tener una división de operador + do causaría problemas para el uso de una clase racional) o como dice Scott Meyers:
Ahora, algunas personas han llevado la sobrecarga del operador al extremo con cosas como boost :: spirit . En este nivel, no tiene idea de cómo se implementa, pero crea una sintaxis interesante para obtener lo que desea hacer. No estoy seguro de si esto es bueno o malo. Parece agradable, pero no lo he usado.
fuente
Nunca he visto un artículo que afirme que la sobrecarga del operador de C ++ es mala.
Los operadores definibles por el usuario permiten un mayor nivel de expresividad y usabilidad para los usuarios del idioma.
fuente
AFAIK, No hay nada especial en las funciones del operador en comparación con las funciones miembro "normales". Por supuesto, solo tiene un cierto conjunto de operadores que puede sobrecargar, pero eso no los hace muy especiales.
fuente