uso sobrecarga que practicas métodos metodos funciones ejercicios ejemplo constructores codificacion buenas java inheritance constructor instance superclass

que - sobrecarga de metodos o funciones en java



Sobrecarga de constructores: mejores prácticas en Java (5)

¿Cuál es un mejor enfoque en caso de consistencia?

  1. Hacer que todos los constructores de niños sean privados.
  2. Introducir métodos estáticos de fábrica.

    ListBubbleSort.withList(List<E> list) ListBubbleSort.withComparator(Comparator<E> comparator)

  3. Hacer una llamada a un super constructor adecuado. No pase ningún null .

    public static <E> ListBubbleSort withList(List<E> list) { return new ListBubbleSort(list); } private ListBubbleSort(List<E>) { super(list); } protected ListSortierer(List<E>) { // initialise only the list field this.origin = list; }

  4. No use Optional como un campo.

    this.original = Optional.ofNullable(li);

  5. Considere el patrón Builder si tiene más de 3 parámetros.

¿Manejar valores perdidos en la superclase abstracta o en la subclase?

Se supone que un constructor proporciona valores iniciales . No estás pasando valores iniciales, solo estás indicando su ausencia .

De forma predeterminada, null es el valor inicial para los tipos de referencia. Por lo tanto, no es necesario reasignar un campo si el valor no se ha dado.

¿Hace una diferencia con respecto a la creación de instancias o es solo una cuestión de opinión?

Legibilidad, mantenimiento.

Recomendaría leer Effective Java de Joshua Bloch :

Creando y destruyendo objetos

  • Ítem ​​1: considerar métodos de fábrica estáticos en lugar de constructores
  • Elemento 2: considerar un constructor cuando se enfrenta con muchos parámetros de constructor

Los constructores también pueden estar sobrecargados como cualquier otro método y soy consciente de ello. Debido a una tarea, decidí usar una superclase abstracta con varios constructores:

Superclase abstracta:

protected ListSortierer() { this( null, null ); } protected ListSortierer( List<E> li ) { this( li, null ); } protected ListSortierer( Comparator<E> comp ) { this( null, comp ); } protected ListSortierer( List<E> li, Comparator<E> com ) { this.original = Optional.ofNullable( li ); this.comp = Optional.ofNullable( com ); }

Para acceder a cada uno de estos constructores, también necesitaba varios constructores en la subclase.

BubbleSort.java:

public ListBubbleSort() { super(); } public ListBubbleSort( List<E> li ) { super( li ); } public ListBubbleSort( Comparator<E> com ) { super( com ); } public ListBubbleSort( List<E> li, Comparator<E> com ) { super( li, com ); }

En este caso, todos los constructores de la subclase llaman al constructor de la superclase inmediatamente. Me vino a la mente que podría referirme nuevamente al propio constructor y pasar null valores null :

public ListBubbleSort() { this( null, null ); } public ListBubbleSort( List<E> li ) { this( li, null ); } public ListBubbleSort( Comparator<E> com ) { this( null, com ); } public ListBubbleSort( List<E> li, Comparator<E> com ) { super( li, com ); }

Hacerlo me permitiría omitir 3 de los constructores sobrecargados en la superclase abstracta, pero obligaría a que cada subclase siga el mismo patrón.

Mi pregunta es: ¿cuál es el mejor enfoque en caso de coherencia? ¿Manejar los valores faltantes en la superclase abstracta o en la subclase? ¿Hace una diferencia con respecto a la creación de instancias o es solo una cuestión de opinión?


Hacerlo me permitiría omitir 3 de los constructores sobrecargados en la superclase abstracta, pero obligaría a que cada subclase siga el mismo patrón.

La ejecución de un contrato se logra a través de métodos abstractos o interfaces. No puede estar seguro de que cada subclase tendrá estos constructores, o al menos no puede estar seguro de que cada subclase agregará estos constructores correctamente.

Entonces, considerando la Encapsulation , estos constructores están mejor en la superclase.


Hacerlo me permitiría omitir 3 de los constructores sobrecargados en la superclase abstracta, pero obligaría a que cada subclase siga el mismo patrón.

Una subclase no tiene ninguna restricción para invocar a un constructor específico de la clase padre. Puede invocar a cualquiera de ellos mientras que esto invoca a uno de ellos.
Por lo que no se pudo lograr tal requisito.

Acerca de la solución utilizando un método de fábrica estática, en algunos casos es aceptable e incluso está bien, pero no es un milagro y también tiene algunas limitaciones.
Por ejemplo: no permite cambiar a otras implementaciones.
Para las clases de JDK, estoy de acuerdo en que casi nunca es un problema, pero para las clases personalizadas debemos usarlo con cuidado.
Además, nada impide que una subclase extienda la clase principal y no pase por una fábrica para crear instancias de esta subclase.
Así que el requisito citado tampoco está asegurado.

Mi pregunta es: ¿cuál es el mejor enfoque en caso de coherencia? ¿Manejar los valores faltantes en la superclase abstracta o en la subclase? ¿Hace una diferencia con respecto a la creación de instancias o es solo una cuestión de opinión?

No es una cuestión de opinión. Importa.
Si la subclase delega a la clase principal y que las comprobaciones son siempre las mismas, parece interesante permitir que la clase principal realice las comprobaciones.
Pero si no tiene garantía de que la clase principal nunca se modifique con respecto a las comprobaciones, las subclases pueden crear algunas instancias de inconsistencia si la clase principal cambia sus comprobaciones.


Puede agregar un addAll final, para ser llamado en los constructores secundarios como extra opcional. Para el comparador la semántica difiere, (casi) se debe sobrecargar cuando es opcional.

private final Optional<Comparator<E>> comparatorOption; public final void addAll(List<E> li) { ...; } protected ListSortierer() { comparatorOption = Optional.empty(); } protected ListSortierer(Comparator<E> comp) { comparatorOption = Optional.of(comp); }

Evitar los parámetros nulos parece mejor.

Prescribir todas las subclases para tener los mismos constructores al tener muchos constructores no es malo si lo desea. La ventaja es que la API para todas las clases se comporta igual. Sin embargo, es un código innecesario de la placa de la caldera, que un patrón de construcción podría evitar. En el antiguo java original, muchos constructores eran el camino a seguir, pero hoy en día se ven muchos constructores en las API.

Para un clasificador de listas, una API fluida con algún tipo de constructor podría ser una idea.

Así que la respuesta final: más una decisión de estilo contextual.


Respecto a la pregunta en sí: creo que ambas opciones no son ideales.

Te esfuerzas por escribir el menor código posible. Tenga cuidado al agregar sobrecargas solo porque parecen convenientes . En realidad, debe hacer lo contrario: piense muy bien cuáles son sus casos de uso reales y solo respalde esos.

Y en su caso, el punto central del ejercicio parece ser permitir la clasificación con diferentes implementaciones. Y en ese sentido, deberías mirar el patrón de estrategia, por ejemplo.

En otras palabras: su primer pensamiento siempre es preferir la composición sobre la herencia . Y cuando su diseño lo lleve a tales preguntas, la mejor respuesta podría ser alejarse de su diseño actual y encontrar una manera de habilitar diferentes clasificaciones como una especie de "servicio", en lugar de hacer una copia de seguridad de la lista en una clasificación.