Чи існує еквівалент Java або методологія для ключового слова typedef в C ++?


244

Походячи з C та C ++, я виявив, що розумне використання typedefє неймовірно корисним. Чи знаєте ви про спосіб досягнення подібної функціональності в Java, чи це механізм Java, шаблон чи якийсь інший ефективний спосіб, який ви використовували?


6
typedef може бути використаний або багато речей, добрих і поганих, хоча не всі згодні з тим, що є. Чи заперечуєте ви сказати, які аспекти typedef, на вашу думку, є цінними? Таким чином ми можемо розповісти вам, як отримати подібні ефекти на Java, або чому це те, що ви не хочете робити на Java. Збірка відповідей нижче кожного передбачає, що ви говорите про улюблене (або найнависніше) використання автора.
PanCrit

3
Мені подобається набирати рідні типи, якщо згодом я можу перетворити його на клас. typedef IndexT int; наприклад. Пізніше, якщо я хочу, щоб IndexT став класом, я просто його реалізую і видаляю typedef. Це допомагає приховувати інформацію.
JR Lawhorne

13
@Alexander - оновлене посилання: ibm.com/developerworks/java/library/j-jtp02216/index.html
Andreas Dolk

1
Я не впевнений, у чому полягають мінуси, але:public interface ScopeFactory { <Scope extends Map<String, Object>> Scope create(...) throws Exception; }
ScootyPuff

2
Ви могли б Scala stackoverflow.com/a/21223102/203968
oluies

Відповіді:


112

У Java є примітивні типи, об'єкти та масиви, і все. Немає типів.


38
Я думаю, більшість людей хочуть typedefпереглянути booleanїх bool.
Томаш Зато - Відновіть Моніку

66
@ TomášZato Я не знаю більшості людей, але, на моєму досвіді, це корисно для додавання семантики на кшталт: typedef int PlayerIDщо дозволяє компілятору переконатися, що PlayerID не використовуються взаємозамінно з іншими вкладками, а також робить код набагато більш читабельним для людей . В основному, це як перерахунок, але без обмеженого набору значень.
weberc2

76
@ TomášZato Це також корисно для скорочення довгих типів, таких як typedef MegaLongTemplateClass<With, Many, Params> IsShorten;.
Олексій Медвещек

32
@ weberc2 ", що дає змогу компілятору переконатися, що програвачі PlayerID не використовуються взаємозамінно з іншими вкладками" - typedefне дозволяє щось подібне. Це просто дає іншу назву для типу.
emlai

7
Також корисно, якщо, наприклад, у вас є якийсь тип ідентифікатора, intі вам потрібно змінити його long, ви повинні змінити його в кожному місці в коді, де ви працюєте з ідентифікатором. Якби у вас було typedef, вам доведеться змінити його лише на 1 місці.
Жардо

101

Якщо це саме ви маєте на увазі, ви можете просто розширити клас, який ви хочете набратиdedef, наприклад:

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

5
Я б заперечував, чи це більше анти-шаблон, ніж використання typedef в C.
Zed

22
Це, безумовно, - не typedefмає жодної проблеми, яку описує стаття для тих підроблених класів (і вони дуже реальні).
Павло Мінаєв

30
@Andreas_D: ваше посилання, виправлено: ibm.com/developerworks/java/library/j-jtp02216/index.html
Янус Трольсен

7
Мені це подобається з тієї ж причини, що мені подобається typedefs. Якщо у вас є контейнер з предметами, можна легко поміняти типи контейнерів, змінивши typedef. Крім того, він може абстрагувати контейнер кінцевому користувачеві (що іноді бажано). Як правило, я б робив це всередині іншого класу, тому тоді тип стає більш очевидним (тобто MyTree.Branches, де розгалуження класів розширюють HashSet <MyTree> {})
Джош Петтіт

8
Хоча головна проблема такого підходу полягає в тому, що ви не можете використовувати його для finalзанять.
AJMansfield

14

На java немає typedef в java, що можна зробити, це зробити клас обгортки для того, що ви хочете, оскільки ви не можете підкласи підсумкових класів (Integer, Double тощо)


3
Посилається на статтю про шаблон, засноване на припущенні, що ви просто хочете скоротити введення тексту (що фактично приховує корисну інформацію про тип). Більшість людей бажає реально використовувати, щоб розмежувати типи та дозволити компілятору робити свою роботу за вас. Дивіться IndexT вище. public Invoice fetchInvoiceItem (String, String, String); проти загальнодоступного рахунку-фактури InvoiceItem (CustomerId, InvoiceId, InvoiceLineItemId); Явні типи плюс перетворювачі / валідатори роблять програмування веб-API, де ВСЕ ВСЕ починається як рядок набагато безпечнішим.
englebart

Ні один оператор oveloading в Java, так що вона не отримує некрасиво
MILS

9

Як вже згадували інші,
у Java немає механізму typedef.
Я також не підтримую "підроблені класи" взагалі, але тут не повинно бути загального суворого правила:
Якщо ваш код, наприклад, використовує знову і знову "загальний тип типу", наприклад:

Map<String, List<Integer>> 

Ви обов'язково повинні врахувати наявність підкласу для цієї мети.
Ще один підхід, який можна врахувати, це, наприклад, уповільнення у своєму коді:

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

А потім використовуйте у своєму коді NameToNumbers і поставте завдання попереднього компілятора (ANT / Gradle / Maven) для обробки та створення відповідного коду Java.
Я знаю, що для деяких читачів цієї відповіді це може здатися дивним, але саме стільки фреймворків реалізували "анотації" до JDK 5, це те, що робить проект lombok та інші рамки.


5

Дійсно, єдиним використанням typedef, який передається в Javaland, є псевдонім, тобто давання тому ж класу декількох імен. Тобто у вас клас "А" і ви хочете, щоб "В" посилався на одне і те ж. У C ++ ви б робили "typedef BA;"

На жаль, вони просто не підтримують це. Однак якщо ви керуєте всіма типовими типами, МОЖЕТЕ витягнути неприємний злом на рівні бібліотеки - ви або подовжуєте B від A, або змушуєте B реалізувати A.


14
Маючи typedefб також корисно створити псевдоніми для викликів родових типів. Наприклад: typedef A<Long,String> B;(це може бути особливий випадок того, що ви описали, але це демонструє привабливість ідеї трохи чіткіше).
igorrs

У моєму випадку використання я хочу надати псевдоніми примітивним типам. real_tза doubleі boolза boolean.
Аарон Франке

3

Можливо, це може стати іншою можливою заміною:

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

2
Ви не думаєте, що зараз це проблема, тому що коли ви визначаєте myMapекземпляр типу MyMap, ви можете працювати на фактичному HashMap тільки ввівши myMapInstance.value.SomeOperation()замість myMapInstance.SomeOperation(). Це дратує, чи не так?
mercury0114

2
ви все ще можете зробити myMapInstance.SomeOperation () - саме для цього і використовується @Delegate
shrewquest

3

Як зазначається в інших відповідях, вам слід уникати антипатерні псевдотипу . Однак typedefs все ще корисні, навіть якщо це не спосіб їх досягнення. Ви хочете розрізняти різні абстрактні типи, які мають однакове представлення Java. Ви не хочете змішувати рядки, що представляють собою паролі, з тими, що представляють собою вуличні адреси, або цілі числа, які представляють зміщення, з тими, що мають ті, що представляють абсолютне значення.

Checker Framework дозволяє визначити ЬурейеЕ в зворотної сумісності способу. Я працюю навіть для примітивних класів, таких як intзаключні класи, такі як String. Він не має накладних витрат та не порушує тести рівності.

Розділ типу псевдонімів та typedefs у посібнику з Checker Framework описує кілька способів створення typedef, залежно від ваших потреб.




-6

Ви можете використовувати Enum, хоча це семантично трохи відрізняється від typedef тим, що він дозволяє лише обмежений набір значень. Іншим можливим рішенням є названий клас обгортки, наприклад

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

але це здається набагато незграбнішим, особливо з огляду на те, що з коду не зрозуміло, що клас не має іншої функції, крім псевдоніму.


-7

Typedef дозволяє елементам неявно присвоювати типи, яких вони не є. Деякі люди намагаються обійти це з допомогою розширень; читайте тут у IBM для пояснення, чому це погана ідея.

Редагувати: Хоча сильний висновок є корисною справою, я не вважаю (і сподіваюся, що ми цього не побачимо) typedefвирощування некрасивої голови на керованих мовах (коли-небудь?).

Редагування 2: У C # ви можете використовувати такий оператор у верхній частині вихідного файлу. Він використовується, тому не потрібно робити другий показаний елемент. Єдиний раз, коли ви бачите зміну імені, це коли область вводить зіткнення імені між двома типами. Перейменування обмежено одним файлом, поза яким кожен тип змінної / параметрів, який він використовував, відомий своїм повним іменем.

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

23
"Typedef дозволяє елементам неявно присвоювати типи, які вони не є" Що? Typedef просто дозволяє створити інше ім’я як псевдонім для типу. Тип все одно точно такий же, ви просто отримаєте для нього коротшу назву. Це не має нічого спільного з висновком типу. -1
jalf

@jalf: Насправді, умовивід типу використовується як рішення саме того, про що ви говорите, але я навев ще один приклад, коли ви можете використовувати "typedef", щоб обійти зіткнення імені.
Сем Харвелл


@AlexanderMalakhov Спасибі, я пішов і оновив відповідь за вашим посиланням
Дейв МакКлелленд

-14

На Java не потрібно вводити typedef. Все є Об'єктом, крім примітивів. Немає покажчиків, лише посилання. Сценарії, в яких ви зазвичай використовуєте typedefs, - це випадки, коли ви створюєте об'єкти.


19
Ні, потреба в typedef все ще існує, якщо ви хочете скоротити назву для типу. Або просто, якщо ви хочете мати можливість замінити використання одного типу іншим, змінивши одне місце у вихідному коді.
jalf

28
@Bill K: meh, скажіть, що після того, як вам довелося ввести щось на зразок std :: map <int, std :: map <std :: string, boost: shared_ptr <std: string>>> :: const_iterator a кілька разів. У цьому випадку typedef скорочення імен підвищує читабельність, а не перешкоджає цьому.
Джоель

22
Перейменування типу може значно покращити читабельність. Що легше читати та розуміти (і, таким чином, читабельніше :) UnmodifiableDirectedGraph<IncrediblyFancyEdgeType, IncrediblyFancyAbstractNode.EvenFancierConcreteNode>чи IncrediblyFancyGraph? Я завжди можу посилатися на визначення, щоб дізнатися, що це насправді. Таким чином я також можу бути впевнений, що не пропущу UnmodifiableDirectedGraph<IncrediblyFancyEdge,IncredilyFancyAbstractNode.SlightlyLessFancyConcreteNode>нудьгу.
Олександр Димитров

10
@AleksandarDimitrov Я знаю, що вашому коментарю вже майже 3 роки, коли я це набираю, але я вважаю, що дуже важливо вказати, наскільки надуманий і нереальний цей приклад: жодне з цих назв класу не містить цього слова Enterprise.
Кейсі

4
Неправильні назви заважають читати. Добрі імена допомагають. Typedefs може допомогти, якщо повне ім’я є настільки довгим, що стає важко читати або вкручувати форматування коду. Це також допоможе при взаємодії з чужими погано обраними або неоднозначними назвами класів. Якщо ви дійсно вважаєте, що typedef по суті буде робити ваш код нечитабельним, то ви також повинні вважати, що ви ніколи не повинні використовувати заяви про імпорт і завжди повинні посилатися на повноцінні назви класів.
Крістофер Барбер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.