C ++ 'da typedef anahtar sözcüğü için bir Java eşdeğeri veya yöntemi var mı?


244

Bir C ve C ++ geçmişinden geldiğimde, typedefinanılmaz derecede yararlı olmak için mantıklı bir kullanım buldum . Java mekanizması, deseni veya kullandığınız diğer etkili bir yöntem olsun, Java'da benzer işlevselliğe ulaşmanın bir yolunu biliyor musunuz?


6
typedef ya da birçok şey kullanılabilir, iyi ve kötü, ama herkes hangisinin üzerinde olduğu konusunda hemfikir değildir. Hangi tip tanımının değerli olduğunu düşündüğünüzü söyler misiniz? Bu şekilde size Java'da nasıl benzer efektler elde edeceğinizi veya neden Java'da yapmak istemediğiniz bir şey olduğunu söyleyebiliriz. Her birinin altındaki cevaplar, yazarın favori (veya en nefret edilen) kullanımından bahsettiğinizi varsayar.
PanCrit

3
Daha sonra bir sınıfa dönüştürebilirsem yerel türleri typedeflemek isterim. typedef IndexT int; Örneğin. Daha sonra, IndexT bir sınıf olmasını istiyorsanız, ben sadece onu uygulamak ve typedef kaldırmak. Bilginin gizlenmesine yardımcı olur.
JR Lawhorne

13

1
Bunun dezavantajları ne olduğundan emin değilim, ama:public interface ScopeFactory { <Scope extends Map<String, Object>> Scope create(...) throws Exception; }
ScootyPuff

2
Sen beğenebilirsin Scala stackoverflow.com/a/21223102/203968
oluies

Yanıtlar:


112

Java ilkel tiplere, nesnelere ve dizilere sahiptir ve hepsi bu kadar. Typedef yok.


38
Sanırım çoğu insan typedefyeniden tanımlamak booleanistiyor bool.
Tomáš Zato - Monica'yı eski durumuna döndür

66
@ TomášZato Çoğu insanı tanımıyorum, ancak tecrübelerime göre, semantik eklemek için kullanışlıdır: typedef int PlayerIDbu da derleyicinin PlayerID'lerin diğer ints ile birbirinin yerine kullanılmadığından emin olmasını sağlar ve ayrıca kod insanlar için çok daha okunabilir hale getirir . Temel olarak, bir enum gibidir, ancak sınırlı bir değer kümesi yoktur.
weberc2

76
@ TomášZato gibi uzun türleri kısaltmak için de yararlıdır typedef MegaLongTemplateClass<With, Many, Params> IsShorten;.
Alex Medveshchek

32
@ weberc2 "derleyicinin PlayerID'lerin diğer ints'lerle dönüşümlü olarak kullanılmadığından emin olmasını sağlar" - typedefböyle bir şeyi etkinleştirmez. Yalnızca bir tür için başka bir ad verir.
emlai

7
Ayrıca, örneğin bir tür kimliğiniz intvarsa ve bunu kimliğinizle değiştirmeniz gerekiyorsa long, kimliğinizle çalıştığınız kodun her yerinde değiştirmeniz gerekir. Eğer olsaydı typedef, sadece 1 yerde değiştirmek zorunda kalacaksın.
Jardo

101

Demek istediğin buysa, yazmak istediğin sınıfı genişletebilirsin, örneğin:

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

5
Bunun C'de typedef kullanmaktan daha fazla anti-kalıp olup olmadığını tartışabilirim
Zed

22
Kesinlikle öyle - typedefmakalenin bu sahte sınıflar için açıkladığı sorunların hiçbirine sahip değil (ve bunlar çok gerçek).
Pavel Minaev


7
Bunu typedefs'i sevdiğim nedenden dolayı seviyorum. Bir nesne kabınız varsa, typedef'i değiştirerek konteyner türlerini değiştirmek kolaydır. Ayrıca, kabı son kullanıcıya soyutlayabilir (bu bazen istenir). Genellikle bunu başka bir sınıfın içinde yapardım, bu yüzden tip daha belirgin hale gelir (yani, Sınıf Branşlarının HashSet <MyTree> {}) genişletildiği MyTree.Branches,
Josh Petitt

8
Her ne kadar bu yaklaşımla ilgili temel sorun, onu finalsınıflarla kullanamamanızdır .
AJMansfield

14

Java'da 1.6'dan beri typedef yok, yapabileceğiniz şey son sınıfları (Integer, Double, vb.) Alt sınıflara ayıramayacağınız için istediğiniz bir sarmalayıcı sınıfı yapmaktır.


3
Başvurulan anti-desen makalesi, yazmanızı kısaltmak istediğiniz varsayımına dayanır (bu da yararlı tür bilgilerini gizler). Çoğu insanın istediği gerçek kullanım türleri belirginleştirmek ve derleyicinin işini sizin için yapmasına izin vermektir. Bkz. Yukarıdaki IndexT. public Invoice fetchInvoiceItem (String, String, String); genel Fatura fetchInvoiceItem'e karşı (CustomerId, InvoiceId, InvoiceLineItemId); Açık türler ve Dönüştürücüler / Doğrulayıcılar, HER ŞEYİN bir Dize olarak başladığı Web API'lerini programlamayı çok daha güvenli hale getirir.
englebart

Java'da aşırı yükleme yok, bu yüzden çirkinleşiyor
mils

9

Diğerlerinin daha önce de belirttiği gibi
, Java'da typedef mekanizması yoktur.
Ayrıca genel olarak "sahte sınıfları" desteklemiyorum, ancak burada genel bir katı kural olmamalıdır:
Örneğin, kodunuz örneğin "genel tabanlı bir tür" üzerinde defalarca kullanırsa:

Map<String, List<Integer>> 

Bu amaçla kesinlikle bir alt sınıfa sahip olmayı düşünmelisiniz.
Birinin düşünebileceği başka bir yaklaşım, örneğin kodunuzda aşağıdaki gibi bir yavaşlamaya sahip olmaktır:

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

Daha sonra NameToNumbers kodunuzda kullanın ve ilgili java kodunu işlemek ve oluşturmak için bir ön derleyici görevine (ANT / Gradle / Maven) sahip olun.
Bu cevabın okuyucularına bazılarının garip gelebileceğini biliyorum, ancak JDK 5'ten önce kaç çerçeve "ek açıklama" uyguladı, proje lombokunun yaptığı şey ve diğer çerçeveler bu.


5

Gerçekten, Javaland'a aktarılan typedef'in tek kullanımı diğer addır - yani aynı sınıfa birden fazla isim verir. Yani, "A" sınıfınız var ve "B" nin aynı şeyi ifade etmesini istiyorsunuz. C ++ ile, "typedef BA;"

Ne yazık ki, sadece desteklemiyorlar. Ancak, ilgili tüm türleri kontrol ederseniz, kütüphane düzeyinde kötü bir hack çekebilirsiniz - B'yi A'dan uzatabilir veya B'yi A uygulayabilirsiniz.


14
Having typedefda jenerik türleri çağrımı için takma ad oluşturmak için faydalı olacaktır. Örneğin: typedef A<Long,String> B;(bu, tanımladığınız şeyin özel bir durumu olabilir, ancak fikrin cazibesini biraz daha net gösterir).
igorrs

Kullanım durumumda, ilkel türlere takma ad vermek istiyorum. real_tiçin doubleve booliçin boolean.
Aaron Franke

3

Belki de bu olası bir başka değişiklik olabilir:

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

2
Bunun artık bir sorunu olduğunu düşünmüyor musunuz, çünkü myMaptür örneğini her tanımladığınızdaMyMap , gerçek HashMap üzerinde yalnızca myMapInstance.value.SomeOperation()yerine yazarak çalışabilirsiniz myMapInstance.SomeOperation(). Bu sinir bozucu, değil mi?
mercury0114

2
hala myMapInstance.SomeOperation () - bunu yapabilirsiniz @ Temsilci bunun için
shrewquest

3

Diğer cevaplarda belirtildiği gibi, sözde-typedef antipatternerinden kaçınmalısınız . Bununla birlikte, typedef'ler, bunları başarmanın yolu olmasa bile, hala yararlıdır. Aynı Java temsiline sahip farklı soyut türleri ayırt etmek istiyorsunuz. Parola olan dizeleri sokak adresleri olan dizelerle veya mutlak değeri temsil edenlerle bir farkı temsil eden tamsayıları karıştırmak istemezsiniz.

Denetleyicisi Çerçeve bir geriye dönük olarak uyumlu bir şekilde bir typedef tanımlamanıza olanak sağlar. Hatta ilkel sınıflar intve son sınıflar için bile çalışıyorum String. Çalışma zamanı ek yükü yoktur ve eşitlik testlerini bozmaz.

Checker Framework kılavuzundaki Bölüm Türü takma adları ve typedefs , ihtiyaçlarınıza bağlı olarak typedefs oluşturmanın çeşitli yollarını açıklar.




-6

Bir Enum kullanabilirsiniz, ancak semantik olarak typedef'ten biraz farklı olsa da, yalnızca sınırlı bir değer kümesine izin verir. Başka bir olası çözüm, adlandırılmış bir sarmalayıcı sınıfıdır;

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

ancak bu, özellikle sınıfın bir takma addan başka bir işlevi olmadığının açık olmadığı göz önüne alındığında, daha karmaşık görünüyor.


-7

Typedef, öğelerin, bulunmadıkları türlere örtük olarak atanmasına izin verir. Bazı insanlar bunu uzantılarla çözmeye çalışırlar; bunun neden kötü bir fikir olduğunu açıklamak için IBM'de okuyun.

Edit: Güçlü tip çıkarım yararlı bir şey olsa da, sanmıyorum (ve umuyoruz olmaz) görmek typedef yönetilen dilde çirkin kafa yetiştirme (hiç?) Görmüyorum.

Düzenleme 2: C # 'da, kaynak dosyanın üst kısmında bunun gibi bir kullanma ifadesi kullanabilirsiniz. Kullanıldığı için gösterilen ikinci öğeyi yapmanız gerekmez. Ad değişikliğini gördüğünüz tek zaman, bir kapsamın iki tür arasında bir ad çakışması başlatmasıdır. Yeniden adlandırma bir dosya ile sınırlıdır, bunun dışında kullanılan her değişken / parametre türü tam adıyla bilinir.

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

23
"Typedef, öğelerin, kullanılmadıkları türlere örtük olarak atanmasına izin verir" Ne? Typedef, yazım için takma ad olarak başka bir ad oluşturmanıza olanak tanır. Tip hala aynı, sadece daha kısa bir isim alırsınız. Tür çıkarımı ile ilgisi yoktur. -1
jalf

@jalf: Aslında, tam olarak bahsettiğiniz şeyin çözümü için tür çıkarımı çözüm olarak kullanılıyor, ancak bir isim çarpışması için "typedef" kullanabileceğiniz başka bir örnek daha verdim.
Sam Harwell


@AlexanderMalakhov Teşekkürler, devam ettim ve cevabınızı bağlantınızla güncelledim
Dave McClelland

-14

Java'da typedef'e gerek yoktur. İlkel olanlar dışında her şey bir Nesnedir. İşaretçi yok, sadece referans var. Normalde typedefs kullanacağınız senaryolar bunun yerine nesne oluşturduğunuz örneklerdir.


19
Hayır, bir tür için daha kısa bir ad istiyorsanız, typedef'e gereksinim vardır. Ya da sadece kaynak koddaki bir yeri değiştirerek bir türün kullanımını başka bir türle değiştirmek istiyorsanız.
jalf

28
@ Fatura K: meh, std :: map <int, std :: map <std :: string, boost :: shared_ptr <std :: string>>> :: const_iterator gibi bir şey yazdıktan sonra Birkaç kez. Bu durumda, bir ad kısaltma typedef okunabilirliği artırır, engellemez.
Joel

22
Bir türü yeniden adlandırmak, okunabilirliği büyük ölçüde artırabilir. Okuması ve kavraması daha kolay (ve dolayısıyla daha okunabilir :) UnmodifiableDirectedGraph<IncrediblyFancyEdgeType, IncrediblyFancyAbstractNode.EvenFancierConcreteNode>veya IncrediblyFancyGraphnedir? Aslında ne hakkında olduğunu öğrenmek için her zaman tanıma başvurabilirim. Bu şekilde, UnmodifiableDirectedGraph<IncrediblyFancyEdge,IncredilyFancyAbstractNode.SlightlyLessFancyConcreteNode>can sıkıcı sıkıntıları kaçırmayacağımdan da emin olabilirim .
Aleksandar Dimitrov

10
@AleksandarDimitrov Yorumunuzu yazarken neredeyse 3 yaşında olduğunu biliyorum, ancak bu örneğin ne kadar içten ve gerçekçi olmayan olduğuna dikkat çekmenin çok önemli olduğunu düşünüyorum: bu sınıf adlarının hiçbiri kelimeyi içermiyor Enterprise.
Casey

4
Kötü isimler okunabilirliği engeller. İyi isimler yardımcı olur. Tam ad varsa, Typedefs okunması zorlaşır veya kod biçimlendirmenizi zorlaştırırsa yardımcı olabilir. Başka birinin zayıf seçilmiş veya belirsiz sınıf isimleriyle etkileşime girerken de yardımcı olacaktır. Bir typedef'in kodunuzu okunamaz hale getireceğine gerçekten inanıyorsanız, asla import ifadelerini kullanmamanız gerektiğine ve her zaman tam nitelikli sınıf adlarına başvurmanız gerektiğine inanmalısınız.
Christopher Barber
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.