È una questione di dove vuoi tracciare la linea. È possibile progettare una lingua che rilevi la validità del downcast implicito:
public static void main(String args[]) {
// An implicit upcast
Fruit parent = new Apple();
// An implicit downcast to Apple
Apple child = parent;
}
Ora estraiamo un metodo:
public static void main(String args[]) {
// An implicit upcast
Fruit parent = new Apple();
eat(parent);
}
public static void eat(Fruit parent) {
// An implicit downcast to Apple
Apple child = parent;
}
Siamo ancora bravi. L'analisi statica è molto più difficile ma ancora possibile.
Ma il problema si presenta nel momento in cui qualcuno aggiunge:
public static void causeTrouble() {
// An implicit upcast
Fruit trouble = new Orange();
eat(trouble);
}
Ora, dove vuoi generare l'errore? Questo crea un dilemma, si può dire che il problema è presente Apple child = parent;
, ma questo può essere confutato da "Ma ha funzionato prima". D'altra parte, l'aggiunta ha eat(trouble);
causato il problema ", ma il punto centrale del polimorfismo è consentire esattamente questo.
In questo caso, puoi svolgere un po 'del lavoro del programmatore, ma non puoi farlo fino in fondo. Più lo prendi prima di arrenderti, più difficile sarà spiegare cosa è andato storto. Quindi, è meglio fermarsi il prima possibile, secondo il principio di segnalare gli errori in anticipo.
A proposito, in Java il downcast che hai descritto non è in realtà un downcast. Questo è un cast generale, che può anche lanciare mele sulle arance. Quindi, tecnicamente parlando, l'idea di @ chi è già qui, non ci sono downcasts in Java, solo "everycasts". Avrebbe senso progettare un operatore downcast specializzato che genererà un errore di compilazione quando il suo tipo di risultato non può essere trovato a valle del suo tipo di argomento. Sarebbe una buona idea rendere "everycast" molto più difficile da usare per scoraggiare i programmatori dall'usarlo senza un motivo molto valido. XXXXX_cast<type>(argument)
Viene in mente la sintassi di C ++ .