stringtranslate.com

Sobrecarga de funciones

En algunos lenguajes de programación , la sobrecarga de funciones o sobrecarga de métodos es la capacidad de crear múltiples funciones con el mismo nombre con diferentes implementaciones. Las llamadas a una función sobrecargada ejecutarán una implementación específica de esa función apropiada para el contexto de la llamada, lo que permitirá que una llamada de función realice diferentes tareas según el contexto.

Por ejemplo, doTask() y doTask(object o) son funciones sobrecargadas. Para llamar a este último, se debe pasar un objeto como parámetro , mientras que el primero no requiere un parámetro y se llama con un campo de parámetro vacío. Un error común sería asignar un valor predeterminado al objeto en la segunda función, lo que resultaría en un error de llamada ambiguo , ya que el compilador no sabría cuál de los dos métodos usar.

Otro ejemplo es una función Imprimir (objeto o) que ejecuta diferentes acciones en función de si se trata de imprimir texto o fotografías. Las dos funciones diferentes pueden sobrecargarse como Print(text_object T); Imprimir (objeto_imagen P) . Si escribimos las funciones de impresión sobrecargadas para todos los objetos que nuestro programa "imprimirá", nunca más tendremos que preocuparnos por el tipo de objeto y por la llamada de función correcta, la llamada siempre es: Imprimir (algo) .

Idiomas que soportan la sobrecarga

Los lenguajes que admiten la sobrecarga de funciones incluyen, entre otros, los siguientes:

Reglas en la sobrecarga de funciones.

Es una clasificación de polimorfismo estático en la que una llamada a función se resuelve utilizando algún algoritmo de "mejor coincidencia", donde la función particular a llamar se resuelve encontrando la mejor coincidencia de los tipos de parámetros formales con los tipos de parámetros reales. Los detalles de este algoritmo varían de un idioma a otro.

La sobrecarga de funciones generalmente se asocia con lenguajes de programación de tipo estático que imponen la verificación de tipos en las llamadas a funciones . Una función sobrecargada es en realidad solo un conjunto de funciones diferentes que tienen el mismo nombre. Para cualquier llamada en particular, el compilador determina qué función sobrecargada usar y lo resuelve en el momento de la compilación . Esto es cierto para lenguajes de programación como Java. [8]

En Java , la sobrecarga de funciones también se conoce como polimorfismo en tiempo de compilación y polimorfismo estático.

La sobrecarga de funciones no debe confundirse con formas de polimorfismo en las que la elección se realiza en tiempo de ejecución, por ejemplo, a través de funciones virtuales , en lugar de estáticamente.

Ejemplo: sobrecarga de funciones en C++

#incluir <iostream> int Volumen ( int s ) { // Volumen de un cubo. devolver s * s * s ; }          double Volumen ( double r , int h ) { // Volumen de un cilindro. devolver 3.1415926 * r * r * static_cast <doble> ( h ) ;}              long Volumen ( long l , int b , int h ) { // Volumen de un cuboide. devolver l * b * h ; }              int main () { std :: cout << Volumen ( 10 ); std :: cout << Volumen ( 2.5 , 8 ); std :: cout << Volumen ( 100l , 75 , 15 ); }              

En el ejemplo anterior, el volumen de cada componente se calcula utilizando una de las tres funciones denominadas "volumen", con la selección basada en el diferente número y tipo de parámetros reales.

Sobrecarga de constructores

Los constructores , utilizados para crear instancias de un objeto, también pueden estar sobrecargados en algunos lenguajes de programación orientados a objetos . Debido a que en muchos lenguajes el nombre del constructor está predeterminado por el nombre de la clase, parecería que sólo puede haber un constructor. Siempre que se necesiten varios constructores, deben implementarse como funciones sobrecargadas. En C++ , los constructores predeterminados no toman parámetros, creando instancias de los miembros del objeto con sus valores predeterminados apropiados, "que normalmente es cero para los campos numéricos y una cadena vacía para los campos de cadena". [9] Por ejemplo, un constructor predeterminado para un objeto de factura de restaurante escrito en C++ podría establecer la propina en 15%:

Factura () : propina ( 0,15 ), // porcentaje total ( 0,0 ) { }     

El inconveniente de esto es que se necesitan dos pasos para cambiar el valor del objeto Bill creado. A continuación se muestra la creación y el cambio de valores dentro del programa principal:

Café de facturas ; café . propina = 0,10 ; café . total = 4,00 ;     

Al sobrecargar el constructor, se podrían pasar la propina y el total como parámetros en el momento de la creación. Esto muestra el constructor sobrecargado con dos parámetros. Este constructor sobrecargado se coloca en la clase al igual que el constructor original que usamos antes. Cuál se utiliza depende de la cantidad de parámetros proporcionados cuando se crea el nuevo objeto Bill (ninguno o dos):

Factura ( doble propina , doble total ) : propina ( propina ), total ( total ) { }       

Ahora, una función que crea un nuevo objeto Bill podría pasar dos valores al constructor y configurar los miembros de datos en un solo paso. A continuación se muestra la creación y configuración de los valores:

Café de facturas ( 0,10 , 4,00 );  

Esto puede resultar útil para aumentar la eficiencia del programa y reducir la longitud del código.

Otra razón para la sobrecarga del constructor puede ser imponer miembros de datos obligatorios. En este caso, el constructor predeterminado se declara privado o protegido (o preferiblemente se elimina desde C++11 ) para hacerlo inaccesible desde el exterior. Para Bill, el total anterior podría ser el único parámetro del constructor, ya que Bill no tiene un valor predeterminado sensato para el total, mientras que la propina tiene por defecto 0,15.

Complicaciones

Dos problemas interactúan y complican la sobrecarga de funciones: el enmascaramiento de nombres (debido al alcance ) y la conversión de tipos implícita .

Si una función se declara en un ámbito y luego se declara otra función con el mismo nombre en un ámbito interno, existen dos posibles comportamientos de sobrecarga naturales: la declaración interna enmascara la declaración externa (independientemente de la firma), o ambas, la declaración interna. y la declaración externa se incluyen en la sobrecarga, y la declaración interna enmascara la declaración externa solo si la firma coincide. El primero está tomado en C++: "en C++, no hay sobrecarga entre ámbitos". [10] Como resultado, para obtener un conjunto de sobrecarga con funciones declaradas en diferentes ámbitos, es necesario importar explícitamente las funciones del ámbito externo al ámbito interno, con la usingpalabra clave.

La conversión de tipos implícita complica la sobrecarga de funciones porque si los tipos de parámetros no coinciden exactamente con la firma de una de las funciones sobrecargadas, pero pueden coincidir después de la conversión de tipos, la resolución depende de qué tipo de conversión se elija.

Estos pueden combinarse de manera confusa: una coincidencia inexacta declarada en un ámbito interno puede enmascarar una coincidencia exacta declarada en un ámbito externo, por ejemplo. [10]

Por ejemplo, para tener una clase derivada con una función sobrecargada que toma a doubleo an int, usando la función que toma an intde la clase base, en C++, se escribiría:

clase B { público : vacío F ( int i ); };      clase D : público B { público : usando B :: F ; vacío F ( doble d ); };           

No incluir los usingresultados en un intparámetro pasado Fen la clase derivada se convierte en un doble y coincide con la función en la clase derivada, en lugar de en la clase base; Incluir da usingcomo resultado una sobrecarga en la clase derivada y, por lo tanto, coincide con la función en la clase base.

Advertencias

Si un método está diseñado con una cantidad excesiva de sobrecargas, puede resultar difícil para los desarrolladores discernir qué sobrecarga se llama simplemente leyendo el código. Esto es particularmente cierto si algunos de los parámetros sobrecargados son de tipos heredados de otros parámetros posibles (por ejemplo, "objeto"). Un IDE puede realizar la resolución de sobrecarga y mostrar (o navegar hasta) la sobrecarga correcta.

La sobrecarga basada en tipos también puede obstaculizar el mantenimiento del código, donde las actualizaciones de código pueden cambiar accidentalmente qué método de sobrecarga elige el compilador. [11]

Ver también

Citas

  1. ^ "Clojure - Aprenda Clojure - Funciones". clojure.org . Consultado el 13 de junio de 2023 .
  2. ^ "Especificación del lenguaje Kotlin". kotlinlang.org .
  3. ^ Bloch 2018, pag. 238-244, §Capítulo 8 Artículo 52: Eliminar advertencias no verificadas.
  4. ^ "37.6. Sobrecarga de funciones". Documentación de PostgreSQL . 2021-08-12 . Consultado el 29 de agosto de 2021 .
  5. ^ "Guía y referencia del usuario de la base de datos PL/SQL". docs.oracle.com . Consultado el 29 de agosto de 2021 .
  6. ^ "Manual de Nim". nim-lang.org .
  7. ^ "Documentos de cristal". cristal-lang.org .
  8. ^ Bloch 2018, pag. 238-244, §Capítulo 8 Artículo 52: Utilice la sobrecarga con prudencia.
  9. ^ Chan, Jamie (2017). Aprenda C# en un día y aprenda bien (edición revisada). pag. 82.ISBN 978-1518800276.
  10. ^ ab Stroustrup, Bjarne . "¿Por qué la sobrecarga no funciona para las clases derivadas?".
  11. ^ Bracha, Gilad (3 de septiembre de 2009). "Sobrecarga sistémica". Habitación 101.

Referencias

enlaces externos