Есть ли эквивалент Java или методология для ключевого слова typedef в C++?


исходя из фона C и C++, я нашел разумное использование typedef чтобы быть невероятно полезны. Знаете ли вы способ достижения подобной функциональности в Java, будь то механизм Java, шаблон или какой-либо другой эффективный способ, который вы использовали?

11 221

11 ответов:

в Java есть примитивные типы, объекты и массивы, и все. Нет типов.

Если это то, что вы имеете в виду, вы можете просто расширить класс, который вы хотели бы typedef, например:

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

в java нет typedef с 1.6, что вы можете сделать, это сделать класс-оболочку для того, что вы хотите, так как вы не можете подкласс конечных классов (Integer, Double и т. д.)

Как уже упоминалось ранее,
В Java нет механизма typedef.
Я также не поддерживаю "поддельные классы" в целом, но здесь не должно быть общего строгого эмпирического правила:
Если ваш код, например, использует снова и снова и снова "универсальный тип", например:

Map<String, List<Integer>> 

вы определенно должны рассмотреть возможность наличия подкласса для этой цели.
Другой подход, который можно рассмотреть, например, иметь в своем коде a замедление типа:

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

а затем использовать в коде NameToNumbers и иметь предварительную задачу компилятора (ANT/Gradle/Maven) для обработки и создания соответствующего кода java.
Я знаю, что для некоторых читателей этого ответа это может показаться странным, но это то, сколько фреймворков реализовали "аннотации" до JDK 5, это то, что project Ломбок и другими структурами.

действительно, единственное использование typedef, которое переносится на Javaland, - это псевдонимы, то есть предоставление одному и тому же классу нескольких имен. То есть, у вас есть класс "A", и вы хотите, чтобы "B" относился к тому же самому. В C++ вы бы делали "typedef B A;"

к сожалению, они просто не поддерживают. Однако, если вы контролируете все задействованные типы, вы можете вытащить неприятный Хак на уровне библиотеки - вы либо расширяете B из A, либо имеете B реализовать A.

Как отмечалось в других ответах, вы должны избегать псевдо-оператора typedef антиобразец. Однако typedefs по-прежнему полезны, даже если это не способ их достижения. Вы хотите различать различные абстрактные типы, которые имеют одно и то же представление Java. Вы не хотите смешивать строки, которые являются паролями, с теми, которые являются уличными адресами, или целыми числами, которые представляют смещение, с теми, которые представляют абсолютное значение.

в Checker Framework позволяет определить typedef обратно совместимым способом. Я работаю даже для примитивных классов, таких как int и заключительные классы, такие как String. Он не имеет накладных расходов во время выполнения и не нарушает тесты равенства.

раздел введите псевдонимы и typedefs в руководстве Checker Framework описано несколько способов создания typedefs, в зависимости от ваших потребностей.

возможно, это может быть еще одна возможная замена:

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

в некоторых случаях привязка аннотации может быть именно то, что вы ищете:

https://github.com/google/guice/wiki/BindingAnnotations

или если вы не хотите зависеть от Guice, просто обычная аннотация может сделать.

вы можете использовать перечисление, хотя это семантически немного отличается от typedef в том, что он позволяет только ограниченный набор значений. Другим возможным решением является именованный класс-оболочка, например

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

но это кажется более неуклюжим, особенно учитывая, что из кода не ясно, что класс не имеет никакой другой функции, кроме как псевдоним.

Typedef позволяет неявно присваивать элементы типам, которые ими не являются. Некоторые люди пытаются обойти это с расширениями; читать здесь в IBM для объяснения, почему это плохая идея.

Edit: хотя сильный вывод типа является полезной вещью, я не думаю (и надеюсь, что мы не будем) видеть typedef выращивание уродливой головы на управляемых языках (когда-либо?).

правка 2: В C#, вы можете использовать оператор using в верхней части файла с исходным текстом. Он используется, так что вы не нужно делать второй пункт. Изменение имени отображается только в том случае, если область вводит конфликт имен между двумя типами. Переименование ограничено одним файлом, за пределами которого каждый тип переменной/параметра, который его использовал, известен по его полному имени.

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

в Java нет необходимости в typedef. Все является объектом, за исключением примитивных. Там нет указателей, только ссылки. Сценарии, в которых вы обычно используете typedefs, являются экземплярами, в которых вы создаете объекты вместо этого.