Si tenemos una función en la clase base y otra función con el mismo nombre en la clase derivada, ¿se puede llamar a la función de la clase base desde el objeto de la clase derivada? Esta es una pregunta interesante y, como experimento, prediga la salida del siguiente programa C++ :
C++
#include <iostream> using namespace std; class Base { public: int f(int i) { cout << "f(int): "; return i+3; } }; class Derived : public Base { public: double f(double d) { cout << "f(double): "; return d+3.3; } }; int main() { Derived* dp = new Derived; cout << dp->f(3) << '\n'; cout << dp->f(3.3) << '\n'; delete dp; return 0; }
La salida de este programa es:
f(double): 6.3 f(double): 6.6
En lugar de la supuesta salida:
f(int): 6 f(double): 6.6
La sobrecarga no funciona para la clase derivada en el lenguaje de programación C++. No hay resolución de sobrecarga entre Base y Derivado. El compilador examina el alcance de Derived, encuentra la función única «doble f (doble)» y la llama. Nunca perturba el alcance (que encierra) de Base. En C++, no hay sobrecarga entre los ámbitos y los ámbitos de clases derivadas no son una excepción a esta regla general. (Ver esto para más ejemplos)
Referencia: preguntas frecuentes técnicas en www.stroustrup.com
Ahora considere la versión Java de este programa:
Java
class Base { public int f(int i) { System.out.print("f (int): "); return i+3; } } class Derived extends Base { public double f(double i) { System.out.print("f (double) : "); return i + 3.3; } } class myprogram3 { public static void main(String args[]) { Derived obj = new Derived(); System.out.println(obj.f(3)); System.out.println(obj.f(3.3)); } }
La salida del programa anterior es:
f (int): 6 f (double): 6.6
Entonces, en Java, la sobrecarga funciona en todos los ámbitos, al contrario que en C++. El compilador de Java determina la versión correcta del método sobrecargado que se ejecutará en tiempo de compilación según el tipo de argumentos utilizados para llamar al método y los parámetros de los métodos sobrecargados de ambas clases que reciben los valores de los argumentos utilizados en la llamada y ejecuta ese método sobrecargado.
Finalmente, intentemos obtener el resultado del siguiente programa C# :
C#
using System; class Base { public int f(int i) { Console.Write("f (int): "); return i + 3; } } class Derived : Base { public double f(double i) { Console.Write("f (double) : "); return i+3.3; } } class MyProgram { static void Main(string[] args) { Derived obj = new Derived(); Console.WriteLine(obj.f(3)); Console.WriteLine(obj.f(3.3)); Console.ReadKey(); // write this line if you use visual studio } }
Nota : Console.ReadKey() se usa para detener la consola. Es similar a getch() en C/C++.
La salida del programa anterior es:
f(double) : 6.3 f(double): 6.6
En lugar de la salida asumida:
f(int) : 6 f(double) : 6.6
Explicación: aquí, el objeto que estamos creando es de la clase derivada, por lo que el compilador dará preferencia a la clase derivada primero y realizará una conversión de tipos implícita si es necesario. Entonces, tan pronto como el compilador llegue a » Console.WriteLine(obj.f(3));», verificará la compatibilidad de los parámetros. Aquí, el valor 3 es de tipo int , que es compatible con el tipo de parámetro double de la función de clase derivada f . Entonces, el compilador realizará la conversión de tipo implícita de int a double . Por lo tanto, vendrá la salida f(doble): 6.3 .
Ahora, cuando el compilador llega a » Console.WriteLine(obj.f(3.3));» , nuevamente dará preferencia a la clase derivada primero y la encontrará invocable. Entonces evaluará la función de clase derivada f . Por lo tanto, vendrá la salida f(doble): 6.6 .
Ahora tomemos otro caso en el que estamos colocando la función de clase base f en la clase derivada y viceversa, como se muestra a continuación:
C#
using System; class Base { public double f(double i) { Console.Write("f (double) : "); return i+3.3; } } class Derived : Base { public int f(int i) { Console.Write("f (int): "); return i + 3; } } class MyProgram { static void Main(string[] args) { Derived obj = new Derived(); Console.WriteLine(obj.f(3)); Console.WriteLine(obj.f(3.3)); Console.ReadKey(); // write this line if you use visual studio } }
Producción:
f (int): 6 f (double) : 6.6
¿Estás sorprendido de ver el resultado esperado? ¿Como es posible?
Bueno, tenemos una respuesta a estas preguntas. Como el objeto que hemos creado es de la clase derivada, el compilador de C# dará preferencia a la clase derivada y, si no encuentra ninguna compatibilidad, se va a la clase base. Entonces, cuando el compilador llega a » Console.WriteLine(obj.f(3));», verificará el método de clase derivada f y lo encontrará invocable, el compilador ejecutará esto y la salida f (int): 6 viene . Ahora, cuando el compilador llega a » Console.WriteLine(obj.f(3.3));»,verificará el método de la clase derivada y descubrirá que no es adecuado ya que el valor 3.3 (doble) no es compatible con el tipo de datos int. Por lo tanto, el compilador ahora preferirá la clase base y allí encontrará la mejor coincidencia, por lo que la ejecutará. Entonces, la salida para ese será f (doble): 6.6 .
El motivo es el mismo que el explicado en el caso del programa C++. En C#, al igual que en C++, no hay resolución de sobrecarga entre la clase Base y la clase Derivada. Además, no hay sobrecarga entre los ámbitos y los ámbitos de clases derivadas no son una excepción a esta regla general. Esto es lo mismo que C++ porque C# está diseñado para estar mucho más cerca de C++, según Anders Hejlsberg , el creador del lenguaje C#.
Este artículo es una contribución de Pravasi Meet . Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.
Publicación traducida automáticamente
Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA