Исходя из фона C и С++, я нашел разумное использование typedef
невероятно полезным. Знаете ли вы, как добиться аналогичной функциональности в Java, будь то механизм Java, шаблон или какой-либо другой эффективный способ, который вы использовали?
Java имеет примитивные типы, объекты и массивы и что он. Нет typedefs.
typedef
переопределял boolean
на bool
.
typedef int PlayerID
который позволяет компилятору гарантировать, что идентификаторы PlayerID не используются взаимозаменяемо с другими int, а также делает код намного более читаемый для человека. По сути, это как enum, но без ограниченного набора значений.
Если это то, что вы имеете в виду, вы можете просто расширить класс, который вы хотите ввести typedef, например:
public class MyMap extends HashMap<String, String> {}
typedef
нет проблем, описанных в статье для этих поддельных классов (и они вполне реальны).
В java от 1.6 нет typedef, вы можете сделать класс-оболочку для того, что хотите, поскольку вы не можете подклассифицировать конечные классы (Integer, Double и т.д.)
Действительно, единственное использование typedef, которое переносится в Javaland, - это сглаживание, то есть предоставление одного и того же класса нескольких имен. То есть, у вас есть класс "A", и вы хотите, чтобы "B" ссылался на одно и то же. В С++ вы будете делать "typedef B A;"
К сожалению, они просто не поддерживают его. Однако, если вы контролируете все задействованные типы, вы можете нанести неприятный взлом на уровне библиотеки - вы либо расширяете B от A, либо имеете B, реализующий A.
typedef
также было бы полезно для создания псевдонимов для вызовов универсальных типов. Например: typedef A<Long,String> B;
(это может быть частный случай того, что вы описали, но он показывает привлекательность идеи немного более четко).
real_t
для double
и bool
для boolean
.
Как уже отмечалось в других ответах, вы должны избегать псевдо-typedef antipattern. Тем не менее, typedefs по-прежнему полезны, даже если это не способ их достижения. Вы хотите различать разные абстрактные типы, которые имеют одно и то же представление Java. Вы не хотите смешивать строки, которые являются паролями, с теми, которые являются уличными адресами, или целыми числами, которые представляют смещение с теми, у которых есть абсолютные значения.
Checker Framework позволяет вам определить typedef в обратном совместимости. Я работаю даже для примитивных классов, таких как int
и конечных классов, таких как String
. Он не имеет накладных расходов во время выполнения и не нарушает тесты на равенство.
Раздел Введите псевдонимы и typedefs в руководстве Checker Framework описано несколько способов создания typedefs в зависимости от ваших потребностей.
В некоторых случаях обязательная аннотация может быть только тем, что вы ищете:
https://github.com/google/guice/wiki/BindingAnnotations
Или, если вы не хотите зависеть от Guice, может быть просто обычная аннотация.
Возможно, это может быть другой возможной заменой:
@Data
public class MyMap {
@Delegate //lombok
private HashMap<String, String> value;
}
myMap
типа MyMap
, вы можете работать с фактическим HashMap, только набрав myMapInstance.value.SomeOperation()
вместо myMapInstance.SomeOperation()
. Это раздражает, не так ли?
Как уже упоминалось ранее,
В Java нет механизма typedef.
Я также не поддерживаю "поддельные классы" вообще, но здесь не должно быть строгого эмпирического правила:
Если ваш код, например, использует многократно и более "общий тип", например:
Map<String, List<Integer>>
Вы должны определенно рассмотреть наличие подкласса для этой цели.
Другой подход, который можно рассмотреть, например, иметь в вашем коде замедление, например:
//@Alias Map<String, List<Integer>> NameToNumbers;
И затем используйте в своем коде NameToNumbers и задайте задачу перед компилятором (ANT/Gradle/Maven) для обработки и создания соответствующего Java-кода.
Я знаю, что некоторым из читателей этого ответа может показаться странным, но это то, сколько фреймворков реализовало "аннотации" до JDK 5, вот какой проект lombok делает и другие фреймворки.
Вы можете использовать Enum, хотя это семантически немного отличается от typedef, поскольку оно допускает только ограниченный набор значений. Другим возможным решением является именованный класс-оболочка, например
public class Apple {
public Apple(Integer i){this.i=i; }
}
но это кажется более неуклюжим, особенно учитывая, что из кода не ясно, что класс не имеет другой функции, кроме как псевдоним.
Typedef позволяет элементам неявно назначать типы, которыми они не являются. Некоторые люди пытаются обойти это с помощью расширений; читайте здесь, в IBM, для объяснения, почему это плохая идея.
Изменить: в то время как вывод о сильном типе - полезная вещь, я не думаю (и надеюсь, что мы не будем) видеть typedef
, воспитывая ее уродливую голову на управляемых языках (когда-либо?).
Изменить 2: В С# вы можете использовать оператор using, подобный этому, в верхней части исходного файла. Он используется, поэтому вам не нужно делать второй отображаемый элемент. Единственный раз, когда вы видите изменение имени, - это когда область вводит столкновение имен между двумя типами. Переименование ограничено одним файлом, за пределами которого каждый используемый тип переменной/параметра известен по его полному имени.
using Path = System.IO.Path;
using System.IO;
В Java нет необходимости в typedef. Все это объект, за исключением примитивов. Нет указателей, только ссылок. Сценарии, в которых вы обычно используете typedefs, являются экземплярами, в которых вы создаете объекты вместо этого.