Existe-t-il un équivalent Java ou une méthodologie pour le mot-clé typedef en C ++?

244

Venant d'un milieu C et C ++, j'ai trouvé que l'utilisation judicieuse de typedefétait incroyablement utile. Connaissez-vous un moyen d'obtenir des fonctionnalités similaires en Java, que ce soit un mécanisme, un modèle Java ou tout autre moyen efficace que vous avez utilisé?

bn.
la source
6
typedef peut être utilisé ou plusieurs choses, bonnes ou mauvaises, mais tout le monde n'est pas d'accord sur ce qui est lequel. Pourriez-vous dire quels aspects du typedef vous paraissent précieux? De cette façon, nous pouvons vous dire comment obtenir des effets similaires en Java ou pourquoi c'est quelque chose que vous ne voulez pas faire en Java. La collection de réponses ci-dessous suppose que vous parlez de l'utilisation préférée (ou la plus détestée) de l'auteur.
PanCrit
3
J'aime taper les types natifs si je peux plus tard en faire une classe. typedef IndexT int; par exemple. Plus tard, si je veux que IndexT soit une classe, je l'implémente simplement et je supprime le typedef. Il aide à cacher les informations.
JR Lawhorne
13
@Alexander - lien mis à jour: ibm.com/developerworks/java/library/j-jtp02216/index.html
Andreas Dolk
1
Je ne sais pas quels sont les inconvénients de cela, mais:public interface ScopeFactory { <Scope extends Map<String, Object>> Scope create(...) throws Exception; }
ScootyPuff
2
Vous pourriez aimer Scala stackoverflow.com/a/21223102/203968
oluies

Réponses:

112

Java a des types, des objets et des tableaux primitifs et c'est tout. Pas de typedefs.

cletus
la source
38
Je suppose que la plupart des gens veulent typedefredéfinir booleanà bool.
Tomáš Zato - Reinstate Monica
66
@ TomášZato Je ne connais pas la plupart des gens, mais d'après mon expérience, c'est utile pour ajouter des sémantiques comme: typedef int PlayerIDce qui permet au compilateur de s'assurer que les PlayerID ne sont pas utilisés de manière interchangeable avec d'autres entrées, et cela rend également le code beaucoup plus lisible pour les humains . Fondamentalement, c'est comme une énumération mais sans un ensemble limité de valeurs.
weberc2
76
@ TomášZato Il est également utile de raccourcir les types longs tels que typedef MegaLongTemplateClass<With, Many, Params> IsShorten;.
Alex Medveshchek
32
@ weberc2 "qui permet au compilateur de s'assurer que les PlayerID ne sont pas utilisés de manière interchangeable avec d'autres entrées" - typedefne permet rien de tel. Il donne juste un autre nom pour un type.
emlai
7
Également utile si, par exemple, vous avez un ID de type intet que vous devez le changer long, vous devez le changer à chaque endroit du code où vous travaillez avec l'ID. Si vous l'aviez fait typedef, vous n'auriez qu'à le changer à un seul endroit.
Jardo
101

Si c'est ce que vous voulez dire, vous pouvez simplement étendre la classe que vous souhaitez taper, par exemple:

public class MyMap extends HashMap<String, String> {}
Zed
la source
5
Je dirais que c'est plus anti-modèle que d'utiliser typedef en C.
Zed
22
C'est certainement - typedefn'a aucun des problèmes que l'article décrit pour ces fausses classes (et ils sont très réels).
Pavel Minaev, le
30
@Andreas_D: votre lien, corrigé: ibm.com/developerworks/java/library/j-jtp02216/index.html
Janus Troelsen
7
J'aime ça pour la même raison que j'aime les typedefs. Si vous avez un conteneur d'objets, il est facile d'échanger les types de conteneurs en modifiant le typedef. En outre, il peut faire abstraction du conteneur à l'utilisateur final (ce qui est parfois souhaitable). Je le fais généralement à l'intérieur d'une autre classe, donc le type devient plus évident (c'est-à-dire MyTree.Branches, où la classe Branches étend HashSet <MyTree> {})
Josh Petitt
8
Bien que le principal problème avec cette approche soit que vous ne puissiez pas l'utiliser avec des finalclasses.
AJMansfield
14

Il n'y a pas de typedef en java à partir de 1.6, ce que vous pouvez faire est de créer une classe wrapper pour ce que vous voulez car vous ne pouvez pas sous-classer les classes finales (Integer, Double, etc.)

z -
la source
3
L'article anti-modèle référencé est basé sur l'hypothèse que vous souhaitez simplement raccourcir votre saisie (ce qui masquerait en fait les informations de type utiles). La vraie utilisation que la plupart des gens veulent est de lever les ambiguïtés et de laisser le compilateur faire son travail pour vous. Voir IndexT ci-dessus. facture publique fetchInvoiceItem (String, String, String); par rapport à la facture publique fetchInvoiceItem (CustomerId, InvoiceId, InvoiceLineItemId); Les types explicites plus les convertisseurs / validateurs rendent la programmation des API Web où TOUT commence comme une chaîne beaucoup plus sûre.
englebart
Aucun opérateur surchargé en java, donc ça devient moche
mils
9

Comme d'autres l'ont déjà mentionné,
il n'y a pas de mécanisme typedef en Java.
Je ne supporte pas non plus les "fausses classes" en général, mais il ne devrait pas y avoir de règle générale stricte ici:
si votre code, par exemple, utilise encore et encore et encore un "type générique" par exemple:

Map<String, List<Integer>> 

Vous devriez certainement envisager d'avoir une sous-classe à cet effet.
Une autre approche que l'on peut envisager, est par exemple d'avoir dans votre code une décélération comme:

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

Ensuite, utilisez dans votre code NameToNumbers et disposez d'une tâche de précompilation (ANT / Gradle / Maven) pour traiter et générer le code java pertinent.
Je sais que pour certains des lecteurs de cette réponse, cela peut sembler étrange, mais c'est le nombre de frameworks qui ont implémenté des "annotations" avant JDK 5, c'est ce que fait le projet lombok et d'autres frameworks.

Yair Zaslavsky
la source
5

Vraiment, la seule utilisation de typedef qui se répercute sur Javaland est l'aliasing, c'est-à-dire donner à la même classe plusieurs noms. Autrement dit, vous avez une classe "A" et vous voulez que "B" se réfère à la même chose. En C ++, vous feriez "typedef BA;"

Malheureusement, ils ne le soutiennent tout simplement pas. Cependant, si vous contrôlez tous les types impliqués, vous POUVEZ tirer un méchant hack au niveau de la bibliothèque - vous étendez B à partir de A ou B implémentez A.

Zack Yezek
la source
14
Avoir typedefserait également utile pour créer des alias pour les appels de types génériques. Par exemple: typedef A<Long,String> B;(cela peut être un cas particulier de ce que vous avez décrit, mais cela montre un peu plus clairement l'attrait de l'idée).
igorrs
Dans mon cas d'utilisation, je veux donner des alias aux types primitifs. real_tpour doubleet boolpour boolean.
Aaron Franke
3

Cela pourrait peut-être être un autre remplacement possible:

@Data
public class MyMap {
    @Delegate //lombok
    private HashMap<String, String> value;
}
astucieuse
la source
2
Ne pensez-vous pas que cela a maintenant un problème parce que chaque fois que vous définissez une myMapinstance de type MyMap, vous ne pouvez opérer sur HashMap réel qu'en tapant à la myMapInstance.value.SomeOperation()place de myMapInstance.SomeOperation(). C'est ennuyeux, non?
mercury0114
2
vous pouvez toujours faire myMapInstance.SomeOperation () - c'est à cela que sert le @Delegate
shrewquest
3

Comme indiqué dans d'autres réponses, vous devez éviter l' anti-motif pseudo-typedef . Cependant, les typedefs sont toujours utiles même si ce n'est pas le moyen de les atteindre. Vous souhaitez faire la distinction entre différents types abstraits qui ont la même représentation Java. Vous ne voulez pas mélanger les chaînes qui sont des mots de passe avec celles qui sont des adresses de rue, ou des entiers qui représentent un décalage avec ceux avec ceux qui représentent une valeur absolue.

Le Checker Framework vous permet de définir un typedef d'une manière rétrocompatible. Je travaille même pour les classes primitives telles que intet les classes finales telles que String. Il n'a pas de temps d'exécution et ne rompt pas les tests d'égalité.

La section Alias ​​de type et typedefs du manuel Checker Framework décrit plusieurs façons de créer des typedefs, selon vos besoins.

mernst
la source
-6

Vous pouvez utiliser un Enum, bien que ce soit sémantiquement un peu différent d'un typedef en ce qu'il n'autorise qu'un ensemble restreint de valeurs. Une autre solution possible est une classe wrapper nommée, par exemple

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

mais cela semble beaucoup plus maladroit, d'autant plus qu'il n'est pas clair d'après le code que la classe n'a pas d'autre fonction que d'alias.

Steve B.
la source
-7

Typedef permet aux éléments d'être implicitement affectés aux types qu'ils ne sont pas. Certaines personnes essaient de contourner ce problème avec des extensions; lisez ici chez IBM pour une explication de pourquoi c'est une mauvaise idée.

Edit: Bien que l'inférence de type forte soit une chose utile, je ne pense pas (et j'espère que nous ne le verrons pas) voir typedefélever sa tête laide dans les langages gérés (jamais?).

Edit 2: En C #, vous pouvez utiliser une instruction using comme celle-ci en haut d'un fichier source. Il est utilisé pour que vous n'ayez pas à faire le deuxième élément affiché. La seule fois où vous voyez le changement de nom, c'est quand une portée introduit une collision de noms entre deux types. Le changement de nom est limité à un fichier, en dehors duquel chaque type de variable / paramètre qui l'a utilisé est connu sous son nom complet.

using Path = System.IO.Path;
using System.IO;
Sam Harwell
la source
23
"Typedef permet aux éléments d'être implicitement affectés à des types qu'ils ne sont pas" Quoi? Typedef vous permet simplement de créer un autre nom comme alias pour le type. Le type est toujours le même, vous obtenez juste un nom plus court pour lui. Cela n'a rien à voir avec l'inférence de type. -1
jalf
@jalf: En fait, l'inférence de type est utilisée comme solution à exactement ce dont vous parlez, mais j'ai donné un autre exemple où vous pouvez utiliser un "typedef" pour contourner une collision de noms.
Sam Harwell
1
lien mis à jour: ibm.com/developerworks/java/library/j-jtp02216/index.html
Alexander Malakhov
@AlexanderMalakhov Merci, je suis allé de l'avant et mis à jour la réponse avec votre lien
Dave McClelland
-14

Il n'y a pas besoin de typedef en Java. Tout est un objet sauf les primitives. Il n'y a pas de pointeurs, seulement des références. Les scénarios dans lesquels vous utiliseriez normalement des typedefs sont des instances dans lesquelles vous créez des objets à la place.

Markus Koivisto
la source
19
Non, le besoin de typedef existe toujours si vous voulez un nom plus court pour un type. Ou tout simplement si vous voulez pouvoir remplacer l'utilisation d'un type par un autre en changeant un endroit dans le code source.
jalf
28
@Bill K: meh, disons qu'après avoir dû taper quelque chose comme std :: map <int, std :: map <std :: string, boost :: shared_ptr <std :: string>>> :: const_iterator a quelques fois. Dans ce cas, un typedef de raccourcissement de nom améliore la lisibilité, pas l'entrave.
Joel
22
Renommer un type peut améliorer considérablement la lisibilité. Qu'est-ce qui est plus facile à lire et à comprendre (et donc plus lisible :) UnmodifiableDirectedGraph<IncrediblyFancyEdgeType, IncrediblyFancyAbstractNode.EvenFancierConcreteNode>ou IncrediblyFancyGraph? Je peux toujours me référer à la définition pour savoir de quoi il s'agit réellement. De cette façon, je peux également être sûr de ne pas manquer UnmodifiableDirectedGraph<IncrediblyFancyEdge,IncredilyFancyAbstractNode.SlightlyLessFancyConcreteNode>l'ennui.
Aleksandar Dimitrov
10
@AleksandarDimitrov Je sais que votre commentaire a presque 3 ans lorsque je tape ceci, mais je pense qu'il est très important de souligner à quel point cet exemple est artificiel et irréaliste: aucun de ces noms de classe ne contient le mot Enterprise.
Casey
4
Les mauvais noms nuisent à la lisibilité. Les bons noms aident. Les typedefs peuvent aider si le nom complet est si long qu'il devient difficile à lire ou qu'il gâche la mise en forme de votre code. Cela aiderait également lors de l'interaction avec les noms de classe mal choisis ou ambigus de quelqu'un d'autre. Si vous pensez vraiment qu'un typedef va intrinsèquement rendre votre code illisible, alors vous devez également croire que vous ne devez jamais utiliser d'instructions d'importation et que vous devez toujours vous référer à des noms de classe pleinement qualifiés.
Christopher Barber