Polimorfismo
En este ejemplo vamos a ver los conceptos de sobrecarga y sobrescritura en Java, utilizando la clase Person y sus subclases Customer y Employee. Estas técnicas permiten personalizar el comportamiento de los métodos en clases hijas y definir múltiples métodos con el mismo nombre en una misma clase, pero con diferentes argumentos.
La clase Person sirve como clase base, y define el método speak(). Las clases Customer y Employee, que heredan de Person, sobrescriben el método speak() para ofrecer comportamientos específicos. Además, en la clase Main, se implementa una serie de métodos sobrecargados llamados speak(), que varían en el tipo de parámetro recibido.
class Person {
public String speak() {
return "I'm a person";
}
}
class Customer extends Person {
public String speak() {
return "I'm a customer";
}
}
class Employee extends Person {
public String speak() {
return "I'm a employee";
}
}
public class Main {
public static String speak(Person person) {
return "I'm a person";
}
public static String speak(Customer customer) {
return "I'm a customer";
}
public static String speak(Employee employee) {
return "I'm a employee";
}
public static void main1() {
Person p1 = new Person();
Customer c1 = new Customer();
Employee e1 = new Employee();
System.out.println(p1.speak()); // "I'm a person"
System.out.println(c1.speak()); // "I'm a customer"
System.out.println(e1.speak()); // "I'm a employee"
}
public static void main(String[] args) {
main1();
}
}
En este caso, los métodos sobrescritos en las clases hijas son llamados según el tipo real del objeto. Esto es posible gracias al polimorfismo en tiempo de ejecución.
public static void main2() {
Person p1 = new Person();
Person c1 = new Customer();
Person e1 = new Employee();
System.out.println(p1.speak()); // "I'm a person"
System.out.println(c1.speak()); // "I'm a customer"
System.out.println(e1.speak()); // "I'm a employee"
}
Aquí, aunque las referencias son del tipo Person, el método sobrescrito es llamado según el tipo real del objeto (Customer o Employee). Esto se resuelve en tiempo de ejecución.
public static void main3() {
Person p1 = new Person();
Customer c1 = new Customer();
Employee e1 = new Employee();
System.out.println(speak(p1)); // "I'm a person"
System.out.println(speak(c1)); // "I'm a customer"
System.out.println(speak(e1)); // "I'm a employee"
}
En este caso, los métodos sobrecargados de la clase Main son seleccionados en tiempo de compilación, según el tipo declarado del argumento.
public static void main4() {
Person p1 = new Person();
Person c1 = new Customer();
Person e1 = new Employee();
System.out.println(speak(p1)); // "I'm a person"
System.out.println(speak(c1)); // "I'm a person"
System.out.println(speak(e1)); // "I'm a person"
}
En este ejemplo, aunque las instancias apuntan a diferentes subclases, el método sobrecargado seleccionado depende del tipo declarado del parámetro (Person), ya que la sobrecarga se resuelve en tiempo de compilación.