¿Vale la pena la complejidad necesaria para evitar que el método anulado del constructor a un método anulado?

7

La invocación de métodos de instancias no finales en constructores conlleva el riesgo de realizar una conversión descendente de un constructor a un método anulado como tal:

public class Start {
    public static void main(String[] args) {
        try {
            ClassB obj = new ClassB();

        } catch(Exception e) { }
    }

        static class ClassA {
            ClassA() { initSomething(); }

            void initSomething() {
                System.out.println("ClassA:: initSomething()...");
            }
        }


        static class ClassB extends ClassA {
            @Override
            void initSomething() {
                System.out.println("ClassB:: initSomething()...");
            }
        }
}

Ahora confías en cada subclase para invocar super.initSomething() .

En muchos de los constructores que he estado viendo, los métodos de instancia reemplazables se invocan . Además, nunca he visto un método marcado como final .

¿Estoy siendo estúpidamente pedante al tener una política de no invocar métodos de instancia no final en los constructores? En realidad, tal derribo es realmente un caso de esquina. ¿Qué hacen los programadores experimentados?

    
pregunta konishiki 14.03.2016 - 01:51

1 respuesta

6
  

¿Estoy siendo estúpidamente pedante teniendo una política de no invocar   ¿Métodos de instancia no final en constructores?

No, pero es importante entender la construcción con más detalle.

  

En realidad, tal derribo en realidad es un caso de esquina. Qué hacer   ¿Los programadores experimentados lo hacen?

No veo ningún "downcasting" pasando aquí, solo invoco métodos invaluables.

El principio básico a tener en cuenta es que un constructor debe terminar con el objeto que se está construyendo en un estado utilizable. Esto se extiende a cada "nivel" de un objeto: el constructor de la superclase debe finalizar completamente y correctamente, entonces el constructor de la subclase se ejecuta e inicializa correctamente su estado.

La idea misma de un método de "inicialización" es un anatema para la programación orientada a objetos, porque el constructor es el método de inicialización (incluso si los constructores no son técnicamente métodos en Java). No tiene sentido confiar en otro método cuando ya tiene un método de inicialización .

Si un constructor utiliza un método, solo debe llamar a los métodos final . De lo contrario, un método podría ser anulado en una subclase. Ese método anulado podría intentar acceder al estado que aún no se ha inicializado porque el constructor de la subclase no se ha ejecutado de otra manera que no sea para llamar a super() . Si el método accede al estado sin inicializar, rompe la regla anterior porque el constructor aún no se ha ejecutado . Rompe el orden de construcción de la superclase a cada subclase.

Por supuesto, como la mayoría de las "reglas" en la metodología orientada a objetos, son más de lo que llamarían ... directrices. Sígalos la mayor parte del tiempo, pero no salte a través de diez aros para evitar saltar a través de uno. Si tiene sentido romper la "regla", entonces cópelo: pero tenga cuidado y pruébelo.

    
respondido por el user22815 14.03.2016 - 03:48

Lea otras preguntas en las etiquetas