¿Existe un equivalente o metodología Java para la palabra clave typedef en C ++?

244

Viniendo de un fondo C y C ++, encontré el uso juicioso de typedefser increíblemente útil. ¿Conoces una manera de lograr una funcionalidad similar en Java, ya sea un mecanismo, patrón u otra forma efectiva de Java que hayas utilizado?

bn.
fuente
66
typedef se puede usar o muchas cosas, buenas y malas, aunque no todos están de acuerdo en cuál es cuál. ¿Te importaría decir qué aspectos de typedef crees que son valiosos? De esa forma, podemos decirte cómo obtener efectos similares en Java o por qué es algo que no quieres hacer en Java. La colección de respuestas debajo de cada una asume que estás hablando del uso favorito (o más odiado) del autor.
PanCrit el
3
Me gusta escribir tipos nativos si luego podría convertirlo en una clase. typedef IndexT int; por ejemplo. Más tarde, si quiero que IndexT sea una clase, simplemente lo implemento y elimino el typedef. Ayuda con la ocultación de información.
JR Lawhorne
13
@Alexander - enlace actualizado: ibm.com/developerworks/java/library/j-jtp02216/index.html
Andreas Dolk
1
No estoy seguro de cuáles son las desventajas de esto, pero:public interface ScopeFactory { <Scope extends Map<String, Object>> Scope create(...) throws Exception; }
ScootyPuff
2
Puede que te guste Scala stackoverflow.com/a/21223102/203968
oluies

Respuestas:

112

Java tiene tipos, objetos y matrices primitivos y eso es todo. No typedefs.

cletus
fuente
37
Supongo que la mayoría de la gente quiere typedefvolver a definir booleana bool.
Tomáš Zato - Restablece a Mónica el
66
@ TomášZato No conozco a la mayoría de las personas, pero en mi experiencia, es útil para agregar semánticas como: lo typedef int PlayerIDque permite que el compilador se asegure de que los ID de jugador no se usen indistintamente con otras entradas, y también hace que el código sea mucho más legible para los humanos . Básicamente, es como una enumeración pero sin un conjunto limitado de valores.
weberc2
76
@ TomášZato También es útil para acortar tipos largos como typedef MegaLongTemplateClass<With, Many, Params> IsShorten;.
Alex Medveshchek
32
@ weberc2 "que permite que el compilador se asegure de que los ID de jugador no se usen indistintamente con otras entradas", typedefno habilita tal cosa. Simplemente le da otro nombre a un tipo.
emlai
77
También es útil si, por ejemplo, tiene algún ID de tipo inty necesita cambiarlo long, debe cambiarlo en todos los lugares del código donde trabaja con el ID. Si lo hubiera hecho typedef, solo tendría que cambiarlo en 1 lugar.
Jardo
101

Si esto es lo que quiere decir, simplemente puede extender la clase que le gustaría escribir def, por ejemplo:

public class MyMap extends HashMap<String, String> {}
Zed
fuente
55
Yo diría si esto es más antipatrón que usar typedef en C.
Zed
22
Definitivamente lo es: typedefno tiene ninguno de los problemas que el artículo describe para esas clases falsas (y son muy reales).
Pavel Minaev
30
@Andreas_D: su enlace, corregido: ibm.com/developerworks/java/library/j-jtp02216/index.html
Janus Troelsen
77
Me gusta esto por la misma razón que me gusta typedefs. Si tiene un contenedor de objetos, es fácil intercambiar tipos de contenedor cambiando el typedef. Además, puede abstraer el contenedor al usuario final (lo que a veces es deseable). Por lo general, haría esto dentro de otra clase, por lo que el tipo se vuelve más obvio (es decir, MyTree.Branches, donde la clase Branches extiende HashSet <MyTree> {})
Josh Petitt
8
Aunque el principal problema con este enfoque es que no se puede usar con finalclases.
AJMansfield
14

No hay typedef en java a partir de 1.6, lo que puede hacer es crear una clase wrapper para lo que desea, ya que no puede subclasificar las clases finales (Integer, Double, etc.)

z -
fuente
3
El artículo antipatrón al que se hace referencia se basa en la suposición de que solo desea acortar su escritura (lo que realmente ocultaría la información de tipo útil). El uso real que la mayoría de la gente quiere es desambiguar los tipos y dejar que el compilador haga su trabajo por usted. Ver IndexT arriba. Factura pública fetchInvoiceItem (String, String, String); versus public Invoice fetchInvoiceItem (CustomerId, InvoiceId, InvoiceLineItemId); Los tipos explícitos más los convertidores / validadores hacen que la programación de API web donde TODO comienza como una cadena sea mucho más segura.
englebart
Ningún operador se desplaza en Java, por lo que se pone feo
mils
9

Como otros han mencionado antes,
no existe un mecanismo typedef en Java.
Tampoco apoyo "clases falsas" en general, pero no debería haber una regla general estricta aquí:
si su código, por ejemplo, usa una y otra vez un "tipo genérico", por ejemplo:

Map<String, List<Integer>> 

Definitivamente deberías considerar tener una subclase para ese propósito.
Otro enfoque que uno puede considerar es, por ejemplo, tener en su código una desaceleración como:

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

Y luego use en su código NameToNumbers y tenga una tarea de precompilador (ANT / Gradle / Maven) para procesar y generar el código Java relevante.
Sé que para algunos de los lectores de esta respuesta esto puede sonar extraño, pero esta es la cantidad de marcos implementados "anotaciones" antes de JDK 5, esto es lo que está haciendo el proyecto lombok y otros marcos.

Yair Zaslavsky
fuente
5

Realmente, el único uso de typedef que se transfiere a Javaland es el alias, es decir, dar a la misma clase múltiples nombres. Es decir, tienes una clase "A" y quieres que "B" se refiera a lo mismo. En C ++, estarías haciendo "typedef BA;"

Desafortunadamente, simplemente no lo admiten. Sin embargo, si controla todos los tipos involucrados, PUEDE hacer un truco desagradable a nivel de la biblioteca: puede extender B desde A o hacer que B implemente A.

Zack Yezek
fuente
14
Tener typedeftambién sería útil para crear alias para invocaciones de tipos genéricos. Por ejemplo: typedef A<Long,String> B;(este puede ser un caso especial de lo que ha descrito, pero muestra el atractivo de la idea un poco más claramente).
igorrs
En mi caso de uso, quiero dar alias a los tipos primitivos. real_tpor doubley boolpara boolean.
Aaron Franke
3

Quizás esto podría ser otro posible reemplazo:

@Data
public class MyMap {
    @Delegate //lombok
    private HashMap<String, String> value;
}
musaraña
fuente
2
¿No cree que esto ahora tiene un problema porque cada vez que define una myMapinstancia de tipo MyMap, puede operar en HashMap real solo escribiendo en myMapInstance.value.SomeOperation()lugar de hacerlo myMapInstance.SomeOperation()? Esto es molesto, ¿no?
mercury0114
2
todavía puedes hacer myMapInstance.SomeOperation () - para eso está el @Delegate
shrewquest
3

Como se señaló en otras respuestas, debe evitar el antipatrón pseudo-typedef . Sin embargo, los typedefs siguen siendo útiles incluso si esa no es la forma de lograrlos. Desea distinguir entre diferentes tipos abstractos que tienen la misma representación de Java. No desea mezclar cadenas que son contraseñas con aquellas que son direcciones de calles, o enteros que representan un desplazamiento con aquellos con aquellos que representan un valor absoluto.

El marco del inspector le permite definir un typedef de una manera compatible con versiones anteriores. Incluso trabajo para clases primitivas como inty clases finales como String. No tiene sobrecarga en tiempo de ejecución y no rompe las pruebas de igualdad.

La sección Alias ​​de tipo y typedefs en el manual de Checker Framework describe varias formas de crear typedefs, según sus necesidades.

Mernst
fuente
-6

Podría usar una Enum, aunque es semánticamente un poco diferente a un typedef, ya que solo permite un conjunto restringido de valores. Otra posible solución es una clase de contenedor con nombre, p. Ej.

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

pero eso parece mucho más torpe, especialmente dado que no está claro en el código que la clase no tiene otra función que un alias.

Steve B.
fuente
-7

Typedef permite que los elementos se asignen implícitamente a tipos que no son. Algunas personas intentan solucionar esto con extensiones; lea aquí en IBM para obtener una explicación de por qué es una mala idea.

Editar: Si bien la inferencia de tipo fuerte es algo útil, no creo (y espero que no lo veamos) typedefcriar su cabeza fea en lenguajes administrados (¿alguna vez?).

Edición 2: en C #, puede usar una declaración de uso como esta en la parte superior de un archivo fuente. Se usa para que no tenga que hacer el segundo elemento que se muestra. La única vez que ve el cambio de nombre es cuando un ámbito introduce una colisión de nombre entre dos tipos. El cambio de nombre está limitado a un archivo, fuera del cual cada variable / tipo de parámetro que lo usó se conoce por su nombre completo.

using Path = System.IO.Path;
using System.IO;
Sam Harwell
fuente
23
"Typedef permite que los elementos se asignen implícitamente a tipos que no son" ¿Qué? Typedef simplemente le permite crear otro nombre como un alias para el tipo. El tipo sigue siendo exactamente el mismo, solo obtienes un nombre más corto para él. No tiene nada que ver con la inferencia de tipos. -1
jalf
@jalf: En realidad, la inferencia de tipos se usa como la solución a exactamente de lo que estás hablando, pero he dado otro ejemplo donde puedes usar un "typedef" para evitar una colisión de nombres.
Sam Harwell
1
enlace actualizado: ibm.com/developerworks/java/library/j-jtp02216/index.html
Alexander Malakhov
@AlexanderMalakhov Gracias, seguí adelante y actualicé la respuesta con tu enlace
Dave McClelland el
-14

No hay necesidad de typedef en Java. Todo es un Objeto excepto las primitivas. No hay punteros, solo referencias. Los escenarios en los que normalmente usaría typedefs son instancias en las que crea objetos en su lugar.

Markus Koivisto
fuente
19
No, la necesidad de typedef todavía existe si desea un nombre más corto para un tipo. O simplemente si desea poder reemplazar el uso de un tipo con otro cambiando un lugar en el código fuente.
jalf
28
@ Bill K: meh, di que después de haber tenido que escribir algo como std :: map <int, std :: map <std :: string, boost :: shared_ptr <std :: string>>> :: const_iterator a pocas veces. En ese caso, un typedef de acortamiento de nombre mejora la legibilidad, no lo dificulta.
Joel el
22
Cambiar el nombre de un tipo puede mejorar la legibilidad drásticamente. ¿Qué es más fácil de leer y comprender (y por lo tanto más legible :) UnmodifiableDirectedGraph<IncrediblyFancyEdgeType, IncrediblyFancyAbstractNode.EvenFancierConcreteNode>o IncrediblyFancyGraph? Siempre puedo referirme a la definición para averiguar de qué se trata realmente. De esa manera, también puedo estar seguro de que no UnmodifiableDirectedGraph<IncrediblyFancyEdge,IncredilyFancyAbstractNode.SlightlyLessFancyConcreteNode>perderé el aburrimiento.
Aleksandar Dimitrov
10
@AleksandarDimitrov Sé que tu comentario tiene casi 3 años mientras escribo esto, pero creo que es muy importante señalar cuán artificial y poco realista es ese ejemplo: ninguno de esos nombres de clase contiene la palabra Enterprise.
Casey
44
Los malos nombres dificultan la legibilidad. Los buenos nombres ayudan. Typedefs puede ayudar si el nombre completo es tan largo que resulta difícil de leer o daña el formato de su código. También ayudaría al interactuar con los nombres de clase poco elegidos o ambiguos de otra persona. Si realmente cree que un typedef inherentemente va a hacer que su código sea ilegible, entonces también debe creer que nunca debe usar declaraciones de importación y siempre debe referirse a nombres de clase completamente calificados.
Christopher Barber