Esiste un equivalente o una metodologia Java per la parola chiave typedef in C ++?


244

Provenendo da un background C e C ++, ho trovato l'uso giudizioso di typedefessere incredibilmente utile. Conosci un modo per ottenere funzionalità simili in Java, che si tratti di un meccanismo, di un modello Java o di un altro modo efficace che hai usato?


6
typedef può essere usato o molte cose, buone e cattive, anche se non tutti sono d'accordo su quale sia. Ti dispiacerebbe dire quali aspetti della tipografia ritieni siano preziosi? In questo modo possiamo dirti come ottenere effetti simili in Java o perché è qualcosa che non vuoi fare in Java. La raccolta di risposte sotto ciascuna presuppone che tu stia parlando dell'uso preferito (o più odiato) dell'autore.
PanCrit,

3
Mi piace scrivere tipi nativi se potessi in seguito trasformarlo in una classe. typedef IndexT int; per esempio. Più tardi, se voglio che IndexT sia una classe, la implemento e rimuovo il typedef. Aiuta a nascondere le informazioni.
JR Lawhorne,


1
Non sono sicuro di quali siano gli svantaggi, ma:public interface ScopeFactory { <Scope extends Map<String, Object>> Scope create(...) throws Exception; }
ScootyPuff il

2
Come si potrebbe Scala stackoverflow.com/a/21223102/203968
oluies

Risposte:


112

Java ha tipi, oggetti e matrici primitivi e basta. Nessun errore di battitura.


38
Credo che la maggior parte delle persone vogliono typedefridefinire booleana bool.
Tomáš Zato - Ripristina Monica il

66
@ TomášZato Non conosco la maggior parte delle persone, ma nella mia esperienza è utile per aggiungere semantiche come: typedef int PlayerIDciò consente al compilatore di assicurarsi che i PlayerID non vengano usati in modo intercambiabile con altri ints e rende il codice molto più leggibile per gli umani . Fondamentalmente, è come un enum ma senza un insieme limitato di valori.
weberc2,

76
@ TomášZato È anche utile accorciare tipi lunghi come typedef MegaLongTemplateClass<With, Many, Params> IsShorten;.
Alex Medveshchek,

32
@ weberc2 "che consente al compilatore di assicurarsi che i PlayerID non vengano utilizzati in modo intercambiabile con altri ints" - typedefnon consente nulla di simile. Dà solo un altro nome per un tipo.
emlai,

7
Utile anche se, ad esempio, hai un ID di tipo inte devi cambiarlo in long, devi cambiarlo in ogni punto del codice in cui lavori con l'ID. Se lo avessi fatto typedef, dovresti cambiarlo in 1 posto.
Jardo

101

Se questo è ciò che intendi, puoi semplicemente estendere la classe che desideri digitare, ad esempio:

public class MyMap extends HashMap<String, String> {}

5
Direi se questo è più anti-pattern che usare typedef in C.
Zed,

22
Lo è sicuramente - typedefnon ha nessuno dei problemi che l'articolo descrive per quelle classi false (e sono molto reali).
Pavel Minaev,


7
Mi piace per lo stesso motivo per cui mi piacciono i typedef. Se si dispone di un contenitore di oggetti, è facile scambiare i tipi di contenitore modificando il typedef. Inoltre, può estrarre il contenitore per l'utente finale (che a volte è desiderabile). Di solito lo farei all'interno di un'altra classe, quindi il tipo diventa più ovvio (ad esempio MyTree.Branches, dove la classe Branches estende HashSet <MyTree> {})
Josh Petitt

8
Sebbene il problema principale con questo approccio sia che non puoi usarlo con le finalclassi.
AJMansfield

14

Non esiste un typedef in java a partire dalla 1.6, quello che puoi fare è creare una classe wrapper per quello che vuoi poiché non puoi sottoclassare le classi finali (Intero, Doppio, ecc.)


3
L'articolo anti-pattern di riferimento si basa sul presupposto che si desidera solo abbreviare la digitazione (che in realtà nasconderebbe le informazioni utili sul tipo). Il vero uso che la maggior parte delle persone desidera è chiarire i tipi e lasciare che il compilatore faccia il suo lavoro per te. Vedi IndexT sopra. public Invoice fetchInvoiceItem (String, String, String); contro public fvoInvoice fetchInvoiceItem (CustomerId, InvoiceId, InvoiceLineItemId); Tipi espliciti più convertitori / validatori rendono la programmazione di API Web in cui TUTTO inizia come una stringa molto più sicura.
englebart

Nessun operatore sta avanzando a java, quindi diventa brutto
mil

9

Come altri hanno già detto in precedenza,
non esiste alcun meccanismo typedef in Java.
Inoltre, in genere non suppongo "classi fasulle", ma qui non dovrebbe esserci una regola empirica generale rigorosa:
se ad esempio il codice utilizza più e più volte un "tipo basato generico":

Map<String, List<Integer>> 

Dovresti assolutamente considerare di avere una sottoclasse a tale scopo.
Un altro approccio che si può prendere in considerazione, ad esempio, è avere nel tuo codice una decelerazione come:

//@Alias Map<String, List<Integer>>  NameToNumbers;

Quindi usa nel tuo codice NameToNumbers e hai un'attività pre-compilatore (ANT / Gradle / Maven) per elaborare e generare il codice java pertinente.
So che ad alcuni dei lettori di questa risposta potrebbe sembrare strano, ma questo è il numero di framework implementati "annotazioni" prima di JDK 5, questo è ciò che sta facendo il progetto lombok e altri framework.


5

In realtà, l'unico uso di typedef che passa a Javaland è l'aliasing, ovvero dare alla stessa classe più nomi. Cioè, hai una classe "A" e vuoi che "B" faccia riferimento alla stessa cosa. In C ++, faresti "typedef BA;"

Sfortunatamente, semplicemente non lo supportano. Tuttavia, se controlli tutti i tipi coinvolti, PUOI tirare un brutto hack a livello di libreria: o estendi B da A o hai B attrezzo A.


14
Avere typedefsarebbe anche utile per creare alias per invocazioni di tipi generici. Ad esempio: typedef A<Long,String> B;(questo potrebbe essere un caso speciale di ciò che hai descritto, ma mostra un po 'più chiaramente l'appeal dell'idea).
igorrs,

Nel mio caso d'uso, voglio dare alias a tipi primitivi. real_tper doublee boolper boolean.
Aaron Franke,

3

Forse questo potrebbe essere un altro possibile rimpiazzo:

@Data
public class MyMap {
    @Delegate //lombok
    private HashMap<String, String> value;
}

2
Non pensi che questo abbia ora un problema perché ogni volta che definisci myMapun'istanza di tipo MyMap, puoi operare su HashMap reale solo digitando myMapInstance.value.SomeOperation()invece di myMapInstance.SomeOperation(). Questo è fastidioso, vero?
mercury0114,

2
puoi ancora fare myMapInstance.SomeOperation () - ecco a cosa serve
@Delegate

3

Come notato in altre risposte, dovresti evitare di antipattern pseudo-tipedef . Tuttavia, i typedef sono ancora utili anche se non è questo il modo di raggiungerli. Si desidera distinguere tra diversi tipi astratti che hanno la stessa rappresentazione Java. Non si desidera mescolare stringhe che sono password con quelli che sono indirizzi stradali o numeri interi che rappresentano un offset con quelli con quelli che rappresentano un valore assoluto.

Il quadro Checker consente di definire un typedef in modo compatibile con le versioni precedenti. Lavoro anche per classi primitive come inte classi finali comeString . Non ha costi di runtime e non interrompe i test di uguaglianza.

La sezione Tipo di alias e typedef nel manuale di Checker Framework descrive diversi modi per creare typedef, a seconda delle esigenze.




-6

Potresti usare un Enum, anche se semanticamente è un po 'diverso da un typedef in quanto consente solo un insieme limitato di valori. Un'altra possibile soluzione è una classe wrapper denominata, ad es

public class Apple {
      public Apple(Integer i){this.i=i; }
}

ma sembra molto più goffo, soprattutto dato che non è chiaro dal codice che la classe non ha altra funzione che come alias.


-7

Typedef consente agli elementi di essere assegnati in modo implicito ai tipi che non sono. Alcune persone cercano di aggirare questo problema con le estensioni; leggi qui su IBM per una spiegazione del perché questa è una cattiva idea.

Modifica: mentre una forte inferenza di tipo è una cosa utile, non credo (e spero che non lo vedremo) typedef allevare la sua brutta testa nelle lingue gestite (mai?).

Modifica 2: in C #, puoi utilizzare un'istruzione using come questa nella parte superiore di un file di origine. Viene utilizzato quindi non è necessario eseguire il secondo elemento visualizzato. L'unica volta che vedi la modifica del nome è quando un ambito introduce una collisione di nomi tra due tipi. La ridenominazione è limitata a un file, al di fuori del quale ogni variabile / tipo di parametro che lo ha utilizzato è noto con il suo nome completo.

using Path = System.IO.Path;
using System.IO;

23
"Typedef consente agli oggetti di essere assegnati in modo implicito a tipi che non sono" Cosa? Typedef ti consente semplicemente di creare un altro nome come alias per il tipo. Il tipo è sempre lo stesso, hai solo un nome più corto. Non ha nulla a che fare con l'inferenza del tipo. -1
jalf

@jalf: In realtà, l'inferenza del tipo viene utilizzata come soluzione esattamente per ciò di cui stai parlando, ma ho fornito un altro esempio in cui è possibile utilizzare un "typedef" per aggirare una collisione di nomi.
Sam Harwell,


@AlexanderMalakhov Grazie, sono andato avanti e ho aggiornato la risposta con il tuo link
Dave McClelland,

-14

Non è necessario typedef in Java. Tutto è un oggetto tranne i primitivi. Non ci sono puntatori, solo riferimenti. Gli scenari in cui normalmente si usano typedefs sono invece istanze in cui si creano oggetti.


19
No, la necessità di typedef esiste ancora se si desidera un nome più breve per un tipo. O semplicemente se vuoi essere in grado di sostituire l'uso di un tipo con un altro cambiando una posizione nel codice sorgente.
jalf,

28
@Bill K: meh, dì che dopo aver digitato qualcosa come std :: map <int, std :: map <std :: string, boost :: shared_ptr <std :: string>>> :: const_iterator a poche volte In tal caso, un typedef che accorcia i nomi migliora la leggibilità, non la ostacola.
Joel,

22
Rinominare un tipo può migliorare drasticamente la leggibilità. Cosa è più facile da leggere e comprendere (e quindi più leggibile :) UnmodifiableDirectedGraph<IncrediblyFancyEdgeType, IncrediblyFancyAbstractNode.EvenFancierConcreteNode>o IncrediblyFancyGraph? Posso sempre fare riferimento alla definizione per scoprire di cosa si tratta effettivamente. In questo modo posso anche essere sicuro che non mi mancherò UnmodifiableDirectedGraph<IncrediblyFancyEdge,IncredilyFancyAbstractNode.SlightlyLessFancyConcreteNode>per pura noia.
Aleksandar Dimitrov

10
@AleksandarDimitrov So che il tuo commento ha quasi 3 anni mentre lo scrivo, ma sento che è molto importante sottolineare quanto l'esempio sia inventato e irrealistico: nessuno di quei nomi di classe contiene la parola Enterprise.
Casey,

4
I nomi errati ostacolano la leggibilità. I buoni nomi aiutano. Typedefs può aiutare se il nome completo è così lungo che diventa difficile da leggere o rovina la formattazione del codice. Aiuterebbe anche quando interagisce con i nomi delle classi scarsamente scelti o ambigui di qualcun altro. Se credi davvero che un typedef renderà intrinsecamente il tuo codice illeggibile, allora dovresti anche credere che non dovresti mai usare le istruzioni di importazione e fare sempre riferimento a nomi di classe pienamente qualificati.
Christopher Barber
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.