Pochodząc z języków C i C ++ uważam, że rozsądne użycie typedef
jest niezwykle pomocne. Czy znasz sposób na osiągnięcie podobnej funkcjonalności w Javie, niezależnie od tego, czy jest to mechanizm Java, wzorzec, czy inny skuteczny sposób, którego używałeś?
244
public interface ScopeFactory { <Scope extends Map<String, Object>> Scope create(...) throws Exception; }
Odpowiedzi:
Java ma prymitywne typy, obiekty i tablice i to wszystko. Brak typedefs.
źródło
typedef
na nowo zdefiniowaćboolean
dobool
.typedef int PlayerID
która pozwala kompilatorowi upewnić się, że PlayerID nie są używane zamiennie z innymi intami, a także sprawia, że kod jest znacznie bardziej czytelny dla ludzi . Zasadniczo jest to jak wyliczenie, ale bez ograniczonego zestawu wartości.typedef MegaLongTemplateClass<With, Many, Params> IsShorten;
.typedef
nie włącza żadnej takiej rzeczy. To po prostu daje inną nazwę dla typu.int
i musisz go zmienić nalong
, musisz zmienić go w każdym miejscu kodu, w którym pracujesz z tym identyfikatorem. Gdybyś miałtypedef
, musiałbyś to zmienić tylko w 1 miejscu.Jeśli to masz na myśli, możesz po prostu rozszerzyć klasę, którą chcesz wpisać, np .:
źródło
typedef
nie ma żadnego problemu opisanego w artykule dla tych fałszywych klas (i są one bardzo realne).final
klasami.W wersji Java nie ma typedef od 1.6, możesz zrobić klasę otoki dla tego, co chcesz, ponieważ nie można podklasować klas końcowych (liczba całkowita, podwójna itp.)
źródło
Jak wspomniano wcześniej,
w Javie nie ma mechanizmu typedef.
Nie popieram też ogólnie „fałszywych klas”, ale nie powinna tu obowiązywać ogólna ścisła zasada:
jeśli na przykład Twój kod używa w kółko „ogólnego typu”, na przykład:
Zdecydowanie powinieneś rozważyć podklasę do tego celu.
Innym podejściem, które można rozważyć, jest na przykład spowolnienie w kodzie:
A następnie użyj w kodzie NameToNumbers i wykonaj zadanie przed kompilatorem (ANT / Gradle / Maven) w celu przetworzenia i wygenerowania odpowiedniego kodu Java.
Wiem, że dla niektórych czytelników tej odpowiedzi może to zabrzmieć dziwnie, ale tyle frameworków zaimplementowało „adnotacje” przed JDK 5, to właśnie robi projekt lombok i inne frameworki.
źródło
Naprawdę, jedynym zastosowaniem typedef, które przenosi się do Javaland, jest aliasing - czyli nadawanie tej samej klasie wielu nazw. Oznacza to, że masz klasę „A” i chcesz, aby „B” odnosiło się do tej samej rzeczy. W C ++ będziesz robił „typedef BA;”
Niestety po prostu tego nie obsługują. Jeśli jednak kontrolujesz wszystkie zaangażowane typy, MOŻESZ pociągnąć nieprzyjemnego hacka na poziomie biblioteki - albo rozszerzasz B z A, albo masz B implementujące A.
źródło
typedef
również byłoby przydatne do tworzenia aliasów dla wywołań typów ogólnych. Na przykład:typedef A<Long,String> B;
(może to być szczególny przypadek tego, co opisałeś, ale bardziej wyraźnie pokazuje atrakcyjność tego pomysłu).real_t
zadouble
ibool
zaboolean
.Być może może to być kolejna możliwa zamiana:
źródło
myMap
instancję typuMyMap
, możesz operować na rzeczywistym HashMap tylko piszącmyMapInstance.value.SomeOperation()
zamiastmyMapInstance.SomeOperation()
. To denerwujące, prawda?Jak zauważono w innych odpowiedziach, należy unikać antypateru pseudo-typedef . Jednak typedefs są nadal przydatne, nawet jeśli nie jest to sposób na ich osiągnięcie. Chcesz rozróżnić różne typy abstrakcyjne, które mają tę samą reprezentację Java. Nie chcesz mieszać ciągów znaków, które są hasłami z tymi, które są adresami ulic lub liczb całkowitych reprezentujących przesunięcie z tymi z tymi, które reprezentują wartość bezwzględną.
Ramowa Checker pozwala na zdefiniowanie typedef w wstecznie zgodny sposób. Pracuję nawet dla prymitywnych klas takich jak
int
i klas końcowych takich jakString
. Nie ma narzutu w czasie wykonywania i nie przełamuje testów równości.Sekcja Aliasy typów i typedefs w podręczniku Checker Framework opisuje kilka sposobów tworzenia typedefs, w zależności od potrzeb.
źródło
Kotlin obsługuje aliasy typów https://kotlinlang.org/docs/reference/type-aliases.html . Możesz zmieniać nazwy typów i typów funkcji.
źródło
W niektórych przypadkach wiążąca adnotacja może być dokładnie tym, czego szukasz:
https://github.com/google/guice/wiki/BindingAnnotations
Lub jeśli nie chcesz polegać na Guice, wystarczy zwykła adnotacja.
źródło
Możesz użyć Enum, chociaż jest to semantycznie nieco inne niż typedef, ponieważ pozwala tylko na ograniczony zestaw wartości. Innym możliwym rozwiązaniem jest nazwana klasa opakowania, np
ale wydaje się to bardziej niezręczne, szczególnie biorąc pod uwagę, że z kodu nie wynika jasno, że klasa nie ma innej funkcji niż jako alias.
źródło
Typedef umożliwia niejawne przypisanie elementów do typów, którymi nie są. Niektóre osoby próbują obejść ten problem za pomocą rozszerzeń; przeczytaj tutaj w IBM, aby uzyskać wyjaśnienie, dlaczego jest to zły pomysł.
Edycja: Mimo że wnioskowanie silnym typem jest przydatne, nie sądzę (i mam nadzieję, że tego nie zobaczymy)
typedef
wychowywanie brzydkiej głowy w zarządzanych językach (kiedykolwiek?).Edycja 2: W języku C # możesz użyć instrukcji using w górnej części pliku źródłowego. Jest używany, więc nie musisz robić drugiego pokazanego elementu. Zmiana nazwy występuje tylko wtedy, gdy zakres wprowadza kolizję nazwy między dwoma typami. Zmiana nazwy jest ograniczona do jednego pliku, poza którym każdy typ zmiennej / parametru, który go używał, jest znany pod pełną nazwą.
źródło
W Javie nie ma potrzeby pisania na maszynie. Wszystko jest przedmiotem oprócz prymitywów. Nie ma żadnych wskaźników, tylko odniesienia. Scenariusze, w których normalnie użyłbyś typedefs, to instancje, w których zamiast tego tworzysz obiekty.
źródło
UnmodifiableDirectedGraph<IncrediblyFancyEdgeType, IncrediblyFancyAbstractNode.EvenFancierConcreteNode>
lubIncrediblyFancyGraph
? Zawsze mogę odwołać się do definicji, aby dowiedzieć się, o co tak naprawdę chodzi. W ten sposób mogę mieć pewność, że nie umknęUnmodifiableDirectedGraph<IncrediblyFancyEdge,IncredilyFancyAbstractNode.SlightlyLessFancyConcreteNode>
z czystej nudy.Enterprise
.