Java: perché non si verifica un overload del metodo basato sul tipo return?

So che questo non è ansible, ma qualcuno può fornire una teoria sul motivo per cui Java ha scelto di non supportarlo? Ti sto chiedendo perché mi sono imbattuto in una situazione in cui penso sarebbe stato bello avere.

Poiché non è necessario acquisire il valore di ritorno di un metodo in Java, nel qual caso il compilatore non può decidere quale sovraccarico utilizzare. Per esempio

boolean doSomething() { ... } int doSomething() { ... } doSomething(); // which one to call??? 

Un aspetto interessante di questa domanda è il fatto che il linguaggio Java vieta i metodi di overload solo per tipo di ritorno. Ma non la JVM:

Si noti che potrebbe esserci più di un metodo di corrispondenza in una class perché mentre il linguaggio Java vieta a una class di dichiarare più metodi con la stessa firma ma tipi di ritorno diversi, la macchina virtuale Java non lo fa. Questa maggiore flessibilità nella macchina virtuale può essere utilizzata per implementare varie funzionalità linguistiche. Ad esempio, i rendimenti covarianti possono essere implementati con i metodi bridge; il metodo bridge e il metodo sottoposto a override avranno la stessa firma ma tipi di ritorno diversi.

Da: Class.getMethod (String, Class …)

Penso che potresti trovare una soluzione nel link sottostante.

Sovraccarico delle funzioni con tipo di ritorno?

Mi sono chiesto perché non supportano anche questo. Certo, se si ignora il valore restituito, il compilatore non avrebbe modo di sapere quale si desiderava. Ma questa è la stessa ambiguità che sorge con il superamento dei null. Piace:

 String doSomething(String s) { ... } String doSomething(Integer s) { ... } ... String out=doSomething(null); 

In questo caso, il compilatore si lamenta solo che la chiamata è ambigua, e devi risolverlo lanciando il null, come:

 String out=doSomething((String)null); 

Potresti fare la stessa cosa con l’overloading per tipo di ritorno:

 String getSomething() { ... } Integer getSomething() { ... } ... Integer n=getSomething(); 

presumibilmente chiamerei la seconda funzione.

 getSomething(); 

sarebbe ambiguo (e in questo esempio, probabilmente inutile, a meno che non abbia effetti collaterali, ma questa è un’altra storia), quindi dovresti dire:

 (String) getSomething(); 

Più realisticamente, forse:

 if ((String) getSomething()==null) ... 

Ma questo è il caso facile. Riesco a vedere un compilatore-scrittore che non vuole supportare questo perché potrebbe diventare molto complicato capire qualcosa di diverso da un semplice compito. Ad esempio, considera:

 String getSomething() { ... }; Integer getSomething() { ... }; String getOtherthing() { ... }; ... if (getSomething().equals(getOtherthing())) ... 

Il compilatore dovrebbe capire che sia String che Integer hanno funzioni uguali, quindi o uno è valido in quel punto. Quindi dovrebbe notare che getOtherthing è una stringa e Integer.equals (String) è improbabile, quindi probabilmente ciò che lo scrittore voleva era String.equals (String). Do-able, ma a quel punto sto iniziando a vedere che nel caso generale, questa potrebbe essere una bestia.

E poi supponiamo di aggiungere:

 Integer getOtherthing() { ... }; 

Ora che cosa fa il compilatore con questa istruzione IF? Potrebbe usare le versioni String di entrambe le funzioni, o il numero intero, ma non la stringa di uno e il numero intero dell’altro. A quel punto dovrebbe insistere su un cast per dirlo, immagino. Ma la complessità sta davvero sfuggendo di mano.

E se è difficile per il compilatore capire cosa intendi veramente, immagina come sarebbe per un altro programmatore che non può cercare tutte le firme di funzioni alla velocità del compilatore.

È perché sei libero di ignorare il valore di ritorno.

Mentre è teoricamente ansible, non è stato usato in Java per la stessa ragione per cui non è stato usato in C ++; in particolare, è stato rilevato che i sovraccarichi basati su tipi di ritorno sono generalmente più confusi per gli sviluppatori, il vantaggio è marginale rispetto ai costi di implementazione, e sarebbe ambiguo nel caso in cui il tipo di ritorno non sia assegnato ad un valore. Per questi motivi l’overload basato sul tipo di ritorno non è supportato.

Penso che uno dei motivi sia che, nella maggior parte dei casi, è ansible determinare il tipo di ritorno di una funzione solo dopo l’esecuzione della funzione anziché prima di questo processo. Pertanto, non può aiutarti a decidere quale funzione di sovraccarico invocare solo in base a diversi tipi di funzioni di restituzione.

la funzione di sovraccarico solo sulla base del tipo di ritorno confonde il compilatore per distinguere tra le chiamate, perché al momento dell’invocazione non si fornisce il tipo restituito, come nel caso dei parametri, quindi si fornisce solo la lista parametri e questo elenco di parametri è l’unico modo per il compilatore di distinguere tra le chiamate di funzione e il valore di ritorno viene ricevuto al completamento della funzione, motivo per cui il tipo di ritorno non contribuisce alla firma della funzione

L’overloading del metodo utilizza la tecnica del polimorfismo del tempo di compilazione. L’override del metodo utilizza la tecnica del polimorfismo del tempo di esecuzione.

Sovraccarico del metodo:

Come detto nelle risposte precedenti, java non supporta l’overloading dei metodi con tipi di ritorno e argomenti diversi. Questo perché, deve determinare quale metodo usare al momento della compilazione stesso. Per rimuovere l’ambiguità, hanno progettato la tecnica di sovraccarico del metodo in questo modo.

Se abbiamo davvero bisogno di sovraccaricare il metodo con tipi diversi e gli stessi argomenti, è ansible che in qualche modo il mehtod prevalga.

Metodo prioritario:

L’override del metodo utilizza la tecnica del polimorfismo di runtime. Quindi il metodo da eseguire non è deciso al momento della compilazione e viene deciso in fase di esecuzione da JVM.

Con i tipi di restituzione in co-variante, possiamo avere un tipo di ritorno diverso nel metodo della sottoclass con gli stessi argomenti della class base.

Esempio di tipo di restituzione in co-variante:

  class BaseClass { BaseClass dosomething(){ System.out.println("Print BaseClass"); return this; } } class AnotherBaseClass extends BaseClass { @Override BaseClass dosomething(){ System.out.println("Print AnotherBaseClass"); return this; } } class SubClass extends AnotherBaseClass { @Override SubClass dosomething(){ /*Here SubClass is co-vairantreturn type*/ System.out.println("Print SubClass"); return this; } public static void main(String args[]){ SubClass s1 = new SubClass(); s1.dosomething(); } } 

Produzione:

Stampa sottoclass

Poiché Java può trasmettere il valore del tipo restituito alla variabile di destinazione, quindi non sa in quale tipo di variabile si sta memorizzando il valore restituito della funzione.