Perché questa convenzione di sintassi?

0

Si dice nel libro (APress Ganesh / Sharma) su Java 7:

You create a method named fill() in the Utilities class with this declaration:

public static <T> void fill(List<T> list, T val)

You declare the generic type parameter T in this method. After the qualifiers public and static, you put <T> and then followed it by return type, method name, and its parameters. This declaration is different from generic classes—you give the generic type parameters after the class name in generic classes.

Ma perché <T> come in public static <T> ? La sintassi è strana e non appare in nessun altro linguaggio Java. Che cosa significa <T> in questo caso e perché viene utilizzato?

    
posta Niklas Rosencrantz 15.09.2013 - 04:22
fonte

2 risposte

3

significa che solo il metodo è generico e consente alla classe di non essere generica (o utilizzare un parametro generico diverso dalla classe)

ad esempio la Collezione toArray metodo ha un parametro, questo permetterà al tipo di matrice di essere diverso dal tipo della collezione, (utile quando il tipo di raccolta è complicato)

le parentesi angolari devono rimanere retrocompatibili con la sintassi esistente (pre 1.5), che lo utilizzava solo per il confronto (ed è ingannato dal C ++ dove hanno affrontato lo stesso problema relativo alla compatibilità con il codice esistente) e in questo modo più vecchio i compilatori soffocheranno esattamente sulla sintassi, che indicherà esattamente dove si trova il problema

quindi scelgono deliberatamente la sintassi perché non è stata utilizzata da nessun'altra parte nella lingua

la posizione nella dichiarazione prima del tipo restituito è quella di non confondere il compilatore quando viene utilizzato un tipo non elaborato (come public List <T> foo(T t) un metodo che restituisce List<T> o un metodo generico che restituisce un grezzo List )

la sintassi di chiamata Class.<T>foo() è ancora una volta per evitare di confondere il compilatore; il < dopo . può significare solo l'inizio di un qualificatore generico, mentre mettendolo dopo il nome del metodo può essere ambiguo:

è foo(MyClass.bar<T,Y>(ab)) che chiama un singolo parametro foo usando il tipo di ritorno di MyClass.bar<T,Y> o un foo che prende 2 booleani, devi sapere se MyClass.bar è un campo o un metodo

    
risposta data 15.09.2013 - 05:59
fonte
2

Da una intervista del 1995 con Alexander Stepanov sul Journal del Dr Dobb: "Sono tornato al generico sviluppo biblioteca nel 1992, quando Bill Worley, che era il mio direttore del laboratorio stabilito un progetto di algoritmi con me di essere il suo direttore. C ++ avuto modelli per allora. ho scoperto che Bjarne aveva fatto un lavoro meraviglioso a progettare modelli. avevo partecipato a diverse discussioni nella fase iniziale presso i Bell Labs sulla progettazione di modelli e sostenuto piuttosto violentemente con Bjarne che dovrebbe rendere i template C ++ come vicino a generici Ada possibile. Penso che ho sostenuto in modo così violento che ha deciso contro questo. ho capito l'importanza di avere funzioni template in C ++ e non solo classi modello, come alcune persone credevano. ho pensato, però, che le funzioni del modello dovrebbe funzionare come farmaci generici Ada, cioè, che dovrebbero essere istanziati in modo esplicito. Bjarne non ha ascoltato a me e ha progettato un meccanismo di funzione di modello in cui i modelli sono io precisato implicitamente utilizzando un meccanismo di sovraccarico. Questa particolare tecnica è diventata cruciale per il mio lavoro perché ho scoperto che mi permetteva di fare molte cose che non erano possibili in Ada. Vedo questo particolare design di Bjarne come un meraviglioso lavoro e sono molto felice che non abbia seguito il mio consiglio. "

In Ada, un generico deve essere istanziato, come ad esempio:

  package IntIo is new TextIo.IntegerIo(int);
  package coerce is new UncheckedConversion(SomeTypeA, SomeTypeB);

In C ++, Stroustrup lo ha impostato in modo da scrivere qualcosa come:

  TextIo.IntegerIo<int>.Put(x);
  ObjectOfTypeB := coerce<SomeTypeA,SomeTypeB>(ObjectOfTypeA);

Stroustrup ha dovuto usare QUALCOSA per indicare il generico e la sua specializzazione. Ha scelto di sovraccaricare le parentesi angolari. Questo inizialmente ha creato problemi. Cosa accadrebbe se la specializzazione del modello richiedesse un'altra specializzazione per i modelli e dovessi chiuderli entrambi? Il lexer vede due closure & gt ;, o > > e lo riconosce come un'operazione di shift. Era necessaria una correzione linguistica successiva per sovraccaricare gli operatori del turno < < e > >.

    
risposta data 15.09.2013 - 18:28
fonte

Leggi altre domande sui tag