Existe um equivalente ou metodologia Java para a palavra-chave typedef em C ++?


244

Vindo de um background C e C ++, achei o uso criterioso de typedefser incrivelmente útil. Você conhece uma maneira de obter funcionalidade semelhante em Java, seja um mecanismo, padrão ou outra maneira eficaz que você tenha usado?


6
typedef pode ser usado ou muitas coisas, boas e ruins, embora nem todos concordem em qual é qual. Você se importaria em dizer quais aspectos do typedef você acha que são valiosos? Dessa forma, podemos dizer como obter efeitos semelhantes em Java ou por que é algo que você não deseja fazer em Java. A coleção de respostas abaixo de cada parte pressupõe que você esteja falando sobre o uso favorito (ou mais odiado) do autor.
PanCrit

3
Eu gosto de digitar tipos nativos, se mais tarde posso transformá-lo em uma classe. typedef IndexT int; por exemplo. Posteriormente, se eu quiser que o IndexT seja uma classe, basta implementá-lo e remover o typedef. Ajuda na ocultação de informações.
JR Lawhorne


1
Eu não tenho certeza do que as desvantagens deste são, mas:public interface ScopeFactory { <Scope extends Map<String, Object>> Scope create(...) throws Exception; }
ScootyPuff

2
Você pode gostar Scala stackoverflow.com/a/21223102/203968
oluies

Respostas:


112

Java tem tipos primitivos, objetos e matrizes e é isso. Sem typedefs.


37
Eu acho que a maioria das pessoas quer typedefredefinir booleanpara bool.
Tomáš Zato - Restabelecer Monica

66
@ TomášZato Eu não conheço a maioria das pessoas, mas, na minha experiência, é útil adicionar semânticas como: o typedef int PlayerIDque permite ao compilador garantir que PlayerIDs não sejam usados ​​de forma intercambiável com outras ints, além de tornar o código muito mais legível para humanos . Basicamente, é como um enum, mas sem um conjunto limitado de valores.
Weberc2

76
@ TomášZato Também é útil encurtar tipos longos como typedef MegaLongTemplateClass<With, Many, Params> IsShorten;.
Alex Medveshchek

32
@ weberc2 ", que permite que o compilador garanta que os PlayerIDs não estejam sendo usados ​​de forma intercambiável com outras entradas" - typedefnão habilita tal coisa. Apenas fornece outro nome para um tipo.
emlai

7
Também é útil se, por exemplo, você tiver algum ID do tipo inte precisar alterá-lo para long, você deve alterá-lo em todos os lugares do código em que trabalha com o ID. Se você tivesse typedef, seria necessário alterá-lo em apenas um lugar.
Jardo

101

Se é isso que você quer dizer, você pode simplesmente estender a classe que deseja digitar, por exemplo:

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

5
Eu diria se este é qualquer anti-padrão mais do que usar typedef em C.
Zed

22
Definitivamente é - typedefnão possui nenhum dos problemas descritos neste artigo para essas classes falsas (e são muito reais).
Pavel Minaev


7
Gosto disso pela mesma razão que gosto de typedefs. Se você possui um contêiner de objetos, é fácil trocar os tipos de contêiner alterando o typedef. Além disso, ele pode abstrair o contêiner para o usuário final (o que às vezes é desejável). Eu costumo fazer isso dentro de outra classe, por isso, em seguida, o tipo torna-se mais óbvias (ou seja MyTree.Branches, onde Ramos classe estende HashSet <minhaarvore> {})
Josh Petitt

8
Embora o principal problema com essa abordagem seja que você não pode usá-la com finalclasses.
precisa saber é o seguinte

14

Não há typedef no java a partir da versão 1.6, o que você pode fazer é criar uma classe de wrapper para o que você deseja, pois você não pode subclassificar as classes finais (Integer, Double, etc)


3
O artigo antipadrão referenciado baseia-se no pressuposto de que você apenas deseja reduzir sua digitação (que na verdade oculta as informações úteis sobre o tipo). O uso real que a maioria das pessoas deseja é desambiguar tipos e deixar o compilador fazer seu trabalho por você. Veja IndexT acima. fatura pública fetchInvoiceItem (String, String, String); versus fatura pública fetchInvoiceItem (CustomerId, InvoiceId, InvoiceLineItemId); Tipos explícitos mais Conversores / Validadores tornam a programação da API da Web onde TUDO começa como uma String muito mais seguro.
Englebart

Nenhum operador oveloading em java, então fica feio
mils

9

Como outros já mencionaram,
não há mecanismo typedef em Java.
Eu também não apoio "classes falsas" em geral, mas não deve haver uma regra geral estrita aqui:
Se o seu código, por exemplo, usa repetidamente e repetidamente um "tipo baseado em genérico", por exemplo:

Map<String, List<Integer>> 

Você definitivamente deve considerar ter uma subclasse para esse fim.
Outra abordagem que se pode considerar é, por exemplo, ter em seu código uma desaceleração como:

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

E então use no seu código NameToNumbers e tenha uma tarefa de pré-compilador (ANT / Gradle / Maven) para processar e gerar código java relevante.
Eu sei que para alguns dos leitores desta resposta isso pode parecer estranho, mas é quantas estruturas implementadas "anotações" antes do JDK 5, é isso que o projeto lombok está fazendo e outras estruturas.


5

Realmente, o único uso do typedef transferido para o Javaland é o alias - ou seja, dando à mesma classe vários nomes. Ou seja, você tem uma classe "A" e deseja que "B" se refira à mesma coisa. Em C ++, você faria "typedef BA;"

Infelizmente, eles simplesmente não o suportam. No entanto, se você controla todos os tipos envolvidos, PODE acionar um hack desagradável no nível da biblioteca - você estende B de A ou implementa B de A.


14
Ter typedeftambém seria útil para criar aliases para invocações de tipos genéricos. Por exemplo: typedef A<Long,String> B;(esse pode ser um caso especial do que você descreveu, mas mostra o apelo da ideia um pouco mais claramente).
igorrs

No meu caso de uso, quero dar aliases a tipos primitivos. real_tpara doublee boolpara boolean.
Aaron Franke

3

Talvez isso possa ser outro possível substituto:

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

2
Você não acha que isso agora tem um problema, porque sempre que você define uma myMapinstância do tipo MyMap, você pode operar no HashMap real apenas digitando em myMapInstance.value.SomeOperation()vez de myMapInstance.SomeOperation(). Isso é chato, não é?
mercury0114

2
você ainda pode fazer myMapInstance.SomeOperation () - é isso que o @Delegate é para
shrewquest

3

Conforme observado em outras respostas, você deve evitar o antipadrão padrão pseudo-tipado . No entanto, typedefs ainda são úteis, mesmo que esse não seja o caminho para alcançá-los. Você deseja distinguir entre diferentes tipos abstratos que têm a mesma representação Java. Você não deseja misturar seqüências de caracteres com senhas com endereços, ou números inteiros que representam um deslocamento com aqueles com aqueles que representam um valor absoluto.

O Checker Framework permite definir um typedef de uma maneira compatível com versões anteriores. Eu trabalho mesmo para classes primitivas como inte classes finais como String. Não possui sobrecarga de tempo de execução e não quebra os testes de igualdade.

Os aliases de tipo de seção e typedefs no manual do Checker Framework descrevem várias maneiras de criar typedefs, dependendo de suas necessidades.




-6

Você pode usar um Enum, embora seja semanticamente um pouco diferente de um typedef, pois ele permite apenas um conjunto restrito de valores. Outra solução possível é uma classe de wrapper nomeada, por exemplo

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

mas isso parece muito mais complicado, especialmente porque não está claro no código que a classe não tem outra função senão como um alias.


-7

Typedef permite que itens sejam atribuídos implicitamente a tipos que não são. Algumas pessoas tentam contornar isso com extensões; leia aqui na IBM para obter uma explicação de por que essa é uma má ideia.

Edit: Embora uma forte inferência de tipo seja uma coisa útil, eu acho que (e espero que não) veremos typedefelevar sua cabeça feia em idiomas gerenciados (nunca?).

Edição 2: em C #, você pode usar uma instrução using como esta na parte superior de um arquivo de origem. É usado para que você não precise executar o segundo item mostrado. A única vez em que você vê a alteração de nome é quando um escopo introduz uma colisão de nome entre dois tipos. A renomeação é limitada a um arquivo, fora do qual cada tipo de variável / parâmetro que o usou é conhecido por seu nome completo.

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

23
"Typedef permite que itens sejam atribuídos implicitamente a tipos que não são" O quê? O Typedef simplesmente permite criar outro nome como um alias para o tipo. O tipo ainda é exatamente o mesmo, você apenas recebe um nome mais curto. Não tem nada a ver com inferência de tipo. -1
jalf 28/07/09

@ jalf: Na verdade, a inferência de tipo é usada como a solução para exatamente o que você está falando, mas dei outro exemplo em que você pode usar um "typedef" para contornar uma colisão de nomes.
23410 Sam Harwell


@AlexanderMalakhov Obrigado, eu fui em frente e atualizado a resposta com o seu link
Dave McClelland

-14

Não há necessidade de typedef em Java. Tudo é um objeto, exceto as primitivas. Não há ponteiros, apenas referências. Os cenários em que você normalmente usaria typedefs são instâncias nas quais você cria objetos.


19
Não, a necessidade de typedef ainda existe se você desejar um nome mais curto para um tipo. Ou apenas se você quiser substituir o uso de um tipo por outro, alterando um local no código-fonte.
jalf

28
@ Bill K: meh, diga que depois de digitar algo como std :: map <int, std :: map <std :: string, boost :: shared_ptr <std :: string>>> :: const_iterator a poucas vezes. Nesse caso, um typedef de encurtamento de nome aprimora a legibilidade, não a atrapalha.
30909 Joel

22
Renomear um tipo pode melhorar drasticamente a legibilidade. O que é mais fácil de ler e compreender (e, portanto, mais legível :) UnmodifiableDirectedGraph<IncrediblyFancyEdgeType, IncrediblyFancyAbstractNode.EvenFancierConcreteNode>ou IncrediblyFancyGraph? Sempre posso me referir à definição para descobrir do que se trata. Dessa forma, também posso ter certeza de que não sentirei falta UnmodifiableDirectedGraph<IncrediblyFancyEdge,IncredilyFancyAbstractNode.SlightlyLessFancyConcreteNode>do puro tédio.
Aleksandar Dimitrov

10
@AleksandarDimitrov Eu sei que seu comentário tem quase 3 anos enquanto digito isso, mas acho que é muito importante ressaltar o quão artificial e irrealista é esse exemplo: nenhum desses nomes de classe contém a palavra Enterprise.
Casey

4
Nomes ruins dificultam a legibilidade. Bons nomes ajudam. Os Typedefs podem ajudar se o nome completo for tão longo que fica difícil ler ou estragar sua formatação de código. Também ajudaria ao interagir com os nomes de classe pouco escolhidos ou ambíguos de outra pessoa. Se você realmente acredita que um typedef torna inerentemente seu código ilegível, também deve acreditar que nunca deve usar instruções de importação e sempre deve se referir a nomes de classes totalmente qualificados.
Christopher Barber
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.