traer sirve que para frente java inheritance overloading

frente - pack java para que sirve



A qué método sobrecargado se llama en Java (5)

Solución específica del problema

En algunos idiomas, los parámetros se resuelven a su tipo dinámico, pero no en java. El compilador ya determina en el momento de la compilación dónde está su getWorkDetail(this); iré. this es de tipo Person , por lo que se getWorkDetail(Person e) . En su caso específico la solución es bastante obvia. Como otros ya han señalado, deberá anular getWorkDetail() en la clase Employee .

Resolviendo métodos a sus tipos de parámetros dinámicos.

Para resolver el problema general de resolver tipos de parámetros en el tiempo de ejecución, se debe evitar el uso de la instanceof operador, ya que generalmente conduce a un código sucio.

Si tiene dos clases diferentes, ya no es posible una solución tan simple como se indicó anteriormente. En estos casos tendrás que utilizar el patrón de visitante .

Considera las siguientes clases:

public interface Animal { default void eat(Food food) { food.eatenBy(this); } void eatMeat(Meat meat); void eatVegetables(Vegetables vegetables); } public class Shark implements Animal { public void eatMeat (Meat food) { System.out.println("Tasty meat!"); } public void eatVegetables (Vegetables food) { System.out.println("Yuck!"); } } public interface Food { void eatenBy(Animal animal); } public class Meat implements Food { public void eatenBy(Animal animal) { animal.eatMeat(this); } } public class Vegetables implements Food { public void eatenBy(Animal animal) { animal.eatVegetables(this); } }

Que puedes llamar así:

Animal animal = new Shark(); Food someMeat = new Meat(); Food someVegetables= new Vegetables(); animal.eat(someMeat); // prints "Tasty meat!" animal.eat(someVegetables); // prints "Yuck!"

Siguiendo el patrón de Animal.eat , Animal.eat llamará Food.eatenBy , que se implementa tanto en la Meat como en las Vegetables . Esas clases llamarán el método más específico eatMeat o eatVegetables , que utiliza los tipos correctos (dinámicos).

Tengo una situación de herencia básica con un método sobrecargado en la súper clase.

public class Person { private String name; private int dob; private String gender; public Person(String theName, int birth, String sex){ name = theName; dob = birth; gender = sex; } public void work(){ getWorkDetail(this); } public void getWorkDetail(Employee e){ System.out.println("This person is an Employee"); } public void getWorkDetail(Person p){ System.out.println("This person is not an Employee"); } }

La siguiente clase de Employee extiende la clase de Person arriba:

public class Employee extends Person { String department; double salary; public Employee(String theName, int birth, String sex){ super(theName, birth, sex); department = "Not assigned"; salary = 30000; } }

El método principal simplemente crea un objeto Employee (tanto de tipo estático como dinámico) y llama a .work() en él:

public static void main(String[] args){ Employee e1 = new Employee("Manager1", 1976, "Female"); e1.work(); }

Esto termina imprimiendo.

This person is not an Employee

Al analizar esto, pensé que dado que tanto el tipo estático como el dinámico del objeto e1 es Employee , llamaría al método sobrecargado en Persona que toma a un Employee como parámetro. Ya que estoy claramente equivocado acerca de esto, abrí un depurador asumiendo que la referencia a "esto" en la línea getWorkDetail(this) en la clase Person debe haberse transformado en su súper clase. Sin embargo esto no es lo que encontré.

Claramente, en este punto del código, this es un objeto Employee , sin embargo, todavía eligió ejecutar el método sobrecargado getWorkDetail(Person p) . ¿Alguien puede explicar este comportamiento?


A diferencia de las anulaciones de métodos, las sobrecargas de métodos se vinculan en función del tipo estático. Y en este caso, getWorkDetail(this) en Person solo conoce el tipo de Person .

La sobrecarga de métodos no está diseñada para proporcionar un comportamiento dinámico en tiempo de ejecución.

Para aprovechar el enlace dinámico, es posible que deba rediseñar su código para anular los métodos, en su lugar:

public static void main(String[] args) throws IOException { new Employee("Manager1", 1976, "Female").getWorkDetail(); new Person("Manager1", 1976, "Female").getWorkDetail(); }

Y modificar el comportamiento basado en la implementación de clases. Por supuesto, puede sobrecargar los métodos, siempre y cuando se ocupe de anular los métodos sobrecargados, si es necesario.

class Person { private String name; private int dob; private String gender; public Person(String theName, int birth, String sex) { name = theName; dob = birth; gender = sex; } public void getWorkDetail() { System.out.println("This person is not an Employee"); } } class Employee extends Person { String department; double salary; public Employee(String theName, int birth, String sex) { super(theName, birth, sex); department = "Not assigned"; salary = 30000; } public void getWorkDetail() { System.out.println("This person is an Employee"); } }


La resolución de sobrecarga ocurre durante el tiempo de compilación, no en tiempo de ejecución.

Por lo tanto, cuando llama a getWorkDetails(this) , se asume que se trata de una Person (que es el tipo estático) y, por lo tanto, se denomina la sobrecarga correspondiente.

Nota: el uso de this clase dentro de Employee la habría convertido en un tipo de Employee . Puedes verificar esto sobrecargando el work() en Employee esta manera.

class Employee extends Person { ... public void work() { getWorkDetails(this); // This should print "This person is an Employee" } }


getWorkDetail (esto) no sabe cuáles son las subclases. llamar a getWorkDetail en su lugar.


Preferencia de llamada

class Foo { static void test(int arg) { System.out.println("int"); } static void test(float arg) { System.out.println("float"); } static void test(Integer arg) { System.out.println("Integer"); } static void test(int... arg) { System.out.println("int..."); } public static void main(String[] arg) { test(6); } }

La salida se imprimirá en la consola. Ahora comenta el primer método de test() y ve cuál es el resultado que viene.

Esta es la preferencia hirarchey en los tipos de datos primitivos. Ahora llegando a tipos derivados declaran una clase FooChild como esta

class FooChild extends Foo { }

y crear dos nuevos métodos en Foo como

static void testChild(Foo foo) { System.out.println("Foo"); } static void testChild(FooChild fooChild) { System.out.println("FooChild"); }

luego, en el método principal, intente llamar a testChild como este testChild(new FooChild()); .