Apakah ada persamaan atau metodologi Java untuk kata kunci typedef di C ++?

244

Berasal dari latar belakang C dan C ++, saya menemukan penggunaan yang bijaksana typedefuntuk menjadi sangat membantu. Apakah Anda tahu cara untuk mencapai fungsi serupa di Jawa, apakah itu mekanisme Java, pola, atau cara efektif lain yang telah Anda gunakan?

bn.
sumber
6
typedef dapat digunakan atau banyak hal, baik dan buruk, meskipun tidak semua orang setuju yang mana. Maukah Anda mengatakan aspek mana dari mengetik yang Anda anggap berharga? Dengan begitu kami dapat memberi tahu Anda cara mendapatkan efek serupa di Jawa atau mengapa itu adalah sesuatu yang tidak ingin Anda lakukan di Jawa. Kumpulan jawaban di bawah masing-masing mengasumsikan Anda berbicara tentang penggunaan favorit penulis (atau yang paling dibenci).
PanCrit
3
Saya suka mengetikkan tipe asli jika nantinya saya mengubahnya menjadi kelas. ketikkan IndexT int; sebagai contoh. Kemudian, jika saya ingin IndexT menjadi sebuah kelas, saya hanya mengimplementasikannya dan menghapus typedef. Ini membantu menyembunyikan informasi.
JR Lawhorne
13
@Alexander - tautan diperbarui: ibm.com/developerworks/java/library/j-jtp02216/index.html
Andreas Dolk
1
Saya tidak yakin apa kerugiannya, tetapi:public interface ScopeFactory { <Scope extends Map<String, Object>> Scope create(...) throws Exception; }
ScootyPuff
2
Anda mungkin menyukai Scala stackoverflow.com/a/21223102/203968
oluies

Jawaban:

112

Java memiliki tipe, objek dan array primitif dan hanya itu. Tidak ada typedefs.

cletus
sumber
37
Saya kira sebagian besar orang ingin typedefmendefinisikan kembali booleanke bool.
Tomáš Zato - Reinstate Monica
66
@ TomášZato Saya tidak tahu kebanyakan orang, tetapi dalam pengalaman saya, ini berguna untuk menambahkan semantik seperti: typedef int PlayerIDyang memungkinkan kompiler memastikan PlayerID tidak digunakan secara bergantian dengan int lainnya, dan itu juga membuat kode lebih mudah dibaca oleh manusia . Pada dasarnya, ini seperti enum tetapi tanpa nilai yang terbatas.
weberc2
76
@ TomášZato Ini juga berguna untuk mempersingkat jenis yang panjang seperti typedef MegaLongTemplateClass<With, Many, Params> IsShorten;.
Alex Medveshchek
32
@ weberc2 "yang memungkinkan kompiler memastikan PlayerIDs tidak digunakan secara bergantian dengan int lainnya" - typedeftidak mengaktifkan hal semacam itu. Itu hanya memberi nama lain untuk suatu tipe.
emlai
7
Juga bermanfaat jika, misalnya, Anda memiliki beberapa tipe ID intdan Anda perlu mengubahnya long, Anda harus mengubahnya di setiap tempat dalam kode tempat Anda bekerja dengan ID tersebut. Jika sudah typedef, Anda hanya perlu mengubahnya di 1 tempat.
Jardo
101

Jika ini yang Anda maksud, Anda bisa memperpanjang kelas yang ingin Anda ketik, misalnya:

public class MyMap extends HashMap<String, String> {}
Zed
sumber
5
Saya akan berdebat apakah ini lebih anti-pola daripada menggunakan typedef dalam C.
Zed
22
Jelas - typedeftidak ada masalah yang dijelaskan artikel untuk kelas-kelas palsu (dan mereka sangat nyata).
Pavel Minaev
30
@Andreas_D: tautan Anda, diperbaiki: ibm.com/developerworks/java/library/j-jtp02216/index.html
Janus Troelsen
7
Saya suka ini karena alasan yang sama saya suka typedef. Jika Anda memiliki wadah benda, mudah untuk bertukar jenis wadah dengan mengubah typedef. Juga, itu bisa mengabstraksikan wadah ke pengguna akhir (yang kadang-kadang diinginkan). Saya biasanya akan melakukan ini di dalam kelas lain, jadi jenisnya menjadi lebih jelas (yaitu MyTree.Branches, di mana Cabang kelas memperluas HashSet <MyTree> {})
Josh Petitt
8
Meskipun masalah utama dengan pendekatan ini adalah bahwa Anda tidak dapat menggunakannya dengan finalkelas.
AJMansfield
14

Tidak ada typedef di java pada 1.6, yang dapat Anda lakukan adalah membuat kelas wrapper untuk apa yang Anda inginkan karena Anda tidak dapat mensubkelas kelas akhir (Integer, Double, dll)

z -
sumber
3
Artikel anti-pola yang dirujuk didasarkan pada asumsi bahwa Anda hanya ingin mempersingkat pengetikan Anda (yang sebenarnya akan menyembunyikan informasi jenis yang bermanfaat). Penggunaan sebenarnya yang diinginkan kebanyakan orang adalah untuk mendisambiguasi tipe dan membiarkan kompiler melakukan tugasnya untuk Anda. Lihat IndexT di atas. Faktur publik fetchInvoiceItem (String, String, String); versus Faktur Publik fetchInvoiceItem (CustomerId, InvoiceId, InvoiceLineItemId); Jenis eksplisit ditambah Pengonversi / Validator membuat pemrograman API Web tempat SEMUA yang dimulai sebagai sebuah String jauh lebih aman.
englebart
Tidak ada operator yang beroperasi di java, jadi itu jelek
mil
9

Seperti orang lain telah sebutkan sebelumnya,
Tidak ada mekanisme typedef di Jawa.
Saya juga tidak mendukung "kelas palsu" secara umum, tetapi seharusnya tidak ada aturan umum yang ketat di sini:
Jika kode Anda misalnya menggunakan berulang-ulang "tipe berbasis generik" misalnya:

Map<String, List<Integer>> 

Anda harus mempertimbangkan untuk memiliki subclass untuk tujuan itu.
Pendekatan lain yang dapat dipertimbangkan, misalnya memiliki kode perlambatan seperti:

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

Dan kemudian gunakan dalam kode NameToNumbers Anda dan memiliki tugas pra kompiler (ANT / Gradle / Maven) untuk memproses dan menghasilkan kode java yang relevan.
Saya tahu bahwa bagi sebagian pembaca jawaban ini ini mungkin terdengar aneh, tetapi ini adalah berapa banyak kerangka kerja yang menerapkan "anotasi" sebelum JDK 5, inilah yang dilakukan proyek lombok dan kerangka kerja lainnya.

Yair Zaslavsky
sumber
5

Sungguh, satu-satunya penggunaan typedef yang dibawa ke Javaland adalah aliasing -yaitu, memberikan kelas beberapa nama yang sama. Artinya, Anda punya kelas "A" dan Anda ingin "B" merujuk ke hal yang sama. Di C ++, Anda akan melakukan "typedef BA;"

Sayangnya, mereka hanya tidak mendukungnya. Namun, jika Anda mengontrol semua jenis yang terlibat, Anda BISA melakukan hack jahat di tingkat perpustakaan - Anda bisa memperpanjang B dari A atau meminta B implement A.

Zack Yezek
sumber
14
Memiliki typedefjuga akan berguna untuk membuat alias untuk pemanggilan tipe generik. Misalnya: typedef A<Long,String> B;(ini mungkin merupakan kasus khusus dari apa yang telah Anda uraikan, tetapi ini menunjukkan daya tarik ide tersebut dengan lebih jelas).
igorrs
Dalam kasus penggunaan saya, saya ingin memberikan alias untuk tipe primitif. real_tuntuk doubledan booluntuk boolean.
Aaron Franke
3

Mungkin ini bisa menjadi pengganti lain yang mungkin:

@Data
public class MyMap {
    @Delegate //lombok
    private HashMap<String, String> value;
}
shrewquest
sumber
2
Tidakkah Anda berpikir bahwa ini sekarang memiliki masalah karena setiap kali Anda mendefinisikan myMapturunan tipe MyMap, Anda dapat beroperasi pada HashMap yang sebenarnya hanya dengan mengetik myMapInstance.value.SomeOperation()alih-alih myMapInstance.SomeOperation(). Ini menyebalkan, bukan?
mercury0114
2
Anda masih dapat melakukan myMapInstance.SomeOperation () - inilah tujuan dari @Delegate
shrewquest
3

Seperti disebutkan dalam jawaban lain, Anda harus menghindari antipattern pseudo-typedef . Namun, typedef masih berguna bahkan jika itu bukan cara untuk mencapainya. Anda ingin membedakan antara berbagai jenis abstrak yang memiliki representasi Java yang sama. Anda tidak ingin mencampur string yang merupakan kata sandi dengan yang merupakan alamat jalan, atau bilangan bulat yang mewakili offset dengan yang memiliki nilai absolut.

The Checker Kerangka memungkinkan Anda untuk menentukan typedef dengan cara mundur-kompatibel. Saya bekerja bahkan untuk kelas primitif seperti intdan kelas akhir seperti String. Ia tidak memiliki overhead run-time dan tidak melanggar tes kesetaraan.

Bagian Ketikkan alias dan typedef di manual Checker Framework menjelaskan beberapa cara untuk membuat typedef, tergantung pada kebutuhan Anda.

pertama
sumber
-6

Anda bisa menggunakan Enum, meskipun secara semantik sedikit berbeda dari typedef karena hanya memungkinkan serangkaian nilai terbatas. Solusi lain yang mungkin adalah kelas wrapper bernama, misalnya

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

tapi itu kelihatannya jauh lebih kikuk, terutama mengingat bahwa tidak jelas dari kode bahwa kelas tidak memiliki fungsi selain sebagai alias.

Steve B.
sumber
-7

Typedef memungkinkan item secara implisit ditugaskan ke jenis yang bukan miliknya. Beberapa orang mencoba menyiasatinya dengan ekstensi; baca di sini di IBM untuk penjelasan mengapa ini adalah ide yang buruk.

Sunting: Sementara inferensi tipe yang kuat adalah hal yang berguna, saya tidak berpikir (dan berharap kami tidak akan) melihat bahwa typedefitu adalah kepala yang buruk dalam bahasa yang dikelola (pernah?).

Sunting 2: Di C #, Anda dapat menggunakan pernyataan menggunakan seperti ini di bagian atas file sumber. Ini digunakan sehingga Anda tidak perlu melakukan item kedua yang ditampilkan. Satu-satunya saat Anda melihat perubahan nama adalah ketika ruang lingkup memperkenalkan tabrakan nama antara dua jenis. Pengubahan nama terbatas pada satu file, di luar setiap variabel / tipe parameter yang digunakan dikenal dengan nama lengkapnya.

using Path = System.IO.Path;
using System.IO;
Sam Harwell
sumber
23
"Typedef memungkinkan item secara implisit ditugaskan ke tipe yang bukan" Apa? Typedef hanya memungkinkan Anda untuk membuat nama lain sebagai alias untuk jenisnya. Jenisnya masih sama persis, Anda hanya mendapatkan nama yang lebih pendek untuk itu. Ini tidak ada hubungannya dengan inferensi tipe. -1
jalf
@jalf: Sebenarnya, tipe inferensi digunakan sebagai solusi untuk apa yang Anda bicarakan, tetapi saya telah memberikan contoh lain di mana Anda dapat menggunakan "typedef" untuk menyiasati tabrakan nama.
Sam Harwell
1
tautan yang diperbarui: ibm.com/developerworks/java/library/j-jtp02216/index.html
Alexander Malakhov
@AlexanderMalakhov Terima kasih, saya melanjutkan dan memperbarui jawabannya dengan tautan Anda
Dave McClelland
-14

Tidak perlu untuk typedef di Jawa. Semuanya adalah Obyek kecuali untuk primitif. Tidak ada petunjuk, hanya referensi. Skenario di mana Anda biasanya menggunakan typedefs adalah contoh di mana Anda membuat objek.

Markus Koivisto
sumber
19
Tidak, kebutuhan untuk mengetik masih ada jika Anda ingin nama yang lebih pendek untuk suatu jenis. Atau hanya jika Anda ingin dapat mengganti penggunaan satu jenis dengan yang lain dengan mengubah satu tempat dalam kode sumber.
jalf
28
@ Bill K: meh, katakan bahwa setelah Anda mengetik sesuatu seperti std :: map <int, std :: map <std :: string, boost :: shared_ptr <std :: string>>> :: const_iterator a beberapa kali. Dalam hal itu, typedef pemendekan nama meningkatkan keterbacaan, bukan menghambatnya.
Joel
22
Mengganti nama suatu tipe dapat meningkatkan keterbacaan secara drastis. Apa yang lebih mudah dibaca dan dipahami (dan karenanya lebih mudah dibaca :) UnmodifiableDirectedGraph<IncrediblyFancyEdgeType, IncrediblyFancyAbstractNode.EvenFancierConcreteNode>atau IncrediblyFancyGraph? Saya selalu bisa merujuk pada definisi untuk mencari tahu apa itu sebenarnya. Dengan begitu saya juga bisa memastikan saya tidak akan melewatkan UnmodifiableDirectedGraph<IncrediblyFancyEdge,IncredilyFancyAbstractNode.SlightlyLessFancyConcreteNode>kebosanan semata.
Aleksandar Dimitrov
10
@AleksandarDimitrov Saya tahu bahwa komentar Anda hampir 3 tahun saat saya mengetik ini, tetapi saya merasa sangat penting untuk menunjukkan betapa dibuat-buat dan tidak realistisnya contoh itu: tidak ada satu pun dari nama-nama kelas yang mengandung kata tersebut Enterprise.
Casey
4
Nama yang buruk menghambat keterbacaan. Nama baik membantu. Typedefs dapat membantu jika ada nama lengkap yang terlalu panjang sehingga sulit dibaca atau mengacaukan pemformatan kode Anda. Ini juga akan membantu ketika berinteraksi dengan nama kelas orang lain yang dipilih dengan buruk atau ambigu. Jika Anda benar-benar percaya bahwa typedef secara inheren akan membuat kode Anda tidak dapat dibaca, maka Anda juga harus percaya bahwa Anda tidak boleh menggunakan pernyataan impor dan harus selalu merujuk pada nama kelas yang sepenuhnya memenuhi syarat.
Christopher Barber