La complessità necessaria per impedire il downcasting dal costruttore al metodo sovrascritto vale la pena?

7

Il richiamo di metodi di istanza non finali nei costruttori rischia il downcasting da un costruttore a un metodo sottoposto a override in quanto tale:

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()...");
            }
        }
}

Ora fai affidamento su ogni sottoclasse per richiamare super.initSomething() .

In molti dei costruttori che ho visto, i metodi di istanza sovrascrivibili sono richiamati. Inoltre, non ho mai visto un metodo contrassegnato come final .

Sono stupidamente pedante avendo una politica di non invocare metodi di istanza non finali nei costruttori? In realtà, questo downcasting è davvero un caso limite. Cosa fanno i programmatori esperti?

    
posta konishiki 14.03.2016 - 01:51
fonte

1 risposta

6

Am I being stupidly pedantic by having a policy of not invoking non-final instance methods in constructors?

No, ma è importante comprendere la costruzione in modo più dettagliato.

In reality, such downcasting really is a corner case. What do experienced programmers do?

Non vedo nessun "downcasting" in corso qui, solo invocando metodi sovrascrivibili.

Il principio fondamentale da tenere presente è che un costruttore deve terminare con l'oggetto che viene costruito in uno stato utilizzabile. Questo si estende a ogni "livello" di un oggetto: il costruttore della superclasse deve terminare completamente e correttamente, quindi il costruttore della sottoclasse gira e inizializza correttamente il suo stato.

L'idea stessa di un metodo di "inizializzazione" è un anatema alla programmazione orientata agli oggetti, perché il costruttore è il metodo di inizializzazione (anche se i costruttori non sono tecnicamente metodi in Java). Non ha senso fare affidamento su un altro metodo quando hai già un metodo di inizializzazione .

Se un costruttore utilizza un metodo, dovrebbe chiamare solo metodi final . Altrimenti, un metodo potrebbe essere sovrascritto in una sottoclasse. Il metodo sottoposto a override potrebbe tentare di accedere a uno stato che non è ancora stato inizializzato perché il costruttore della sottoclasse non ha eseguito altro che chiamare super() . Se il metodo accede allo stato non inizializzato, interrompe la regola sopra perché il costruttore non ha ancora eseguito veramente . Interrompe l'ordine di costruzione dalla superclasse a ciascuna sottoclasse.

Ovviamente, come la maggior parte delle "regole" nella metodologia orientata agli oggetti, sono più quelle che chiamereste ... linee guida. Seguiteli per la maggior parte del tempo, ma non saltare attraverso dieci cerchi per evitare di saltarne uno. Se ha senso rompere la "regola", allora rompila: ma fai attenzione, e testala.

    
risposta data 14.03.2016 - 03:48
fonte

Leggi altre domande sui tag