Dlaczego Java nie zezwala na używanie nagłówków, jak w C ++


18

Mam pytanie, na które nie znalazłem odpowiedzi, z wyjątkiem następującej odpowiedzi, która nie spełnia moich wymagań:

„Ponieważ James Gosling nie chciał”

Wiem, że Java może mieć interfejsy (tylko funkcje wirtualne, bez atrybutów), ale nie jest to dokładnie to samo, co definicje klas.


14
Z jakiego powodu chcesz je?

19
Aby mieć więcej czasu na walki na miecze;)
Dan04

6
Podejrzewam, że większość programistów C ++ chciałaby pozbyć się 40-letniego silnika zamiany tekstu powielającego setki kLoC dla każdego pliku CPP, co prowadzi do długich czasów kompilacji C ++. W rzeczywistości rozważano odpowiedni system modułów dla C ++ 11, ale spadł on z powodu braku czasu. Ale przypuszczam, że znowu się pojawi.
sbi 11.11.11

Ale przypuszczam, że znowu się pojawi. W rzeczywistości WG21 (grupa robocza ISO C ++) ma grupę badawczą wyłącznie w celu dalszej oceny / rozwoju koncepcji „modułów”: SG2 „Moduły”. Szkoda, że ​​obecny stan jest uśpiony .
Max Truxa

Odpowiedzi:


46

Następująca odpowiedź, która nie spełnia moich wymagań: „Ponieważ James Gosling nie chciał”.

To jednak właściwa odpowiedź. Zespół projektantów języków (Gosling, Sheridan, Naughton, później Bill Joy, Ken Arnold itp.) Zdecydował, że nagłówki powodują więcej problemów niż rozwiązują . Zaprojektowali je i zademonstrowali, że potrafią stworzyć doskonale użyteczny język bez ich potrzeby.

Z sekcji 2.2.1 białej księgi dotyczącej środowiska językowego Java :

Kod źródłowy napisany w Javie jest prosty. Nie ma preprocesora, nie ma #define i powiązanych funkcji, nie ma typedef i nie ma tych funkcji, nie ma już potrzeby plików nagłówkowych. Zamiast plików nagłówkowych pliki źródłowe języka Java zawierają definicje innych klas i ich metod.

Nadmiarowe definicje, synchronizacja plików, sprzeczne definicje, ukryte definicje - żadne z nich nie występuje w Javie, ponieważ nie masz nagłówków. Jeśli chcesz zobaczyć czystą definicję klasy, możesz wygenerować ją bezpośrednio z pliku .java - np. Większość IDE pokaże ci strukturę klasy na pasku bocznym, co odpowiada tej samej rzeczy.


6
Dzięki za odpowiedź, dlatego nagłówki spowodowały więcej problemów z tego powodu: Nadmiarowe definicje, synchronizacja plików, sprzeczne definicje, ukryte definicje. Czy to dlatego nie było dozwolone?
Etienne Noël,

2
Zauważ, że dużo mówi się o kolejnych spotkaniach komitetu C ++, ponieważ rozważą nowy system „Moduł”, który byłby prostszym i bardziej wydajnym systemem niż obejmowanie (z pewnymi podobieństwami z pakietami Java, C # itp.), Ale wciąż retro -kompatybilny z obejmuje. To znaczy, że lepszy system kompilacji można, przynajmniej teoretycznie, wykorzystać do ulepszenia / zwiększenia wydajności kompilacji C ++. Gosling miał rację, a C ++ i tak musi znaleźć sposób na naprawienie systemu dołączania.
Klaim,

5
Nie jest doskonale użyteczny. Systemy kompilacji Java nie są w stanie określić, które pliki należy ponownie skompilować po zmianie kodu. IDE określi, które pliki wymagają zmiany kodu, ale nie te, które wymagają ponownej kompilacji. Jeśli podpis metody zmienia się, ale zmiana jest zgodna ze starym kodem (np. Zmiana typu argumentu z float na double), wymagana jest czysta kompilacja, aby zapobiec MethodNotFoundException.
kevin cline

1
@kevin: Jednak zwykle można po prostu wszystko odbudować bez nadmiernych kosztów. W przeciwieństwie do C ++ (ale jak prawie każdego innego skompilowanego języka na ziemi) Java po prostu nie zajmuje tak dużo czasu, aby kompilacja częściowa była bardzo opłacalna.
Donal Fellows

1
@Donal: To prawda, że ​​Java kompiluje się dość szybko, ale nie lubię zgadywać, czy powinienem przeprowadzić pełną rekompilację. Kompilacje powinny po prostu działać za każdym razem.
kevin cline

16

W C ++ nie ma potrzeby posiadania definicji klas i deklaracji w osobnych plikach. Oznacza to po prostu, że możesz, przynajmniej w czasach C, wykonać analizę składniową za pomocą pojedynczego skanowania kodu od góry do dołu. Na maszynach bez magazynu o dostępie swobodnym była to wielka sprawa!

Posiadanie nagłówków pozwoliło ci również opublikować interfejs do biblioteki kodu, dostarczając nagłówek bez konieczności ujawniania kodu źródłowego. Niestety w C ++ musisz również ujawnić prywatnych członków danych, co doprowadziło do rozwiązań takich jak horror pimpl .

Podjęto próby stworzenia środowiska C ++, w którym wszystko było przechowywane w strukturze typu bazy danych i nie ma żadnych plików, ale się nie przyzwyczaiło.


Wiem o tym, ale przynajmniej możesz to zrobić w C ++, a nie w Javie; to było moje główne zapytanie. Dziękuję za odpowiedź.
Etienne Noël,

14

Z powodu zasady DRY . W Javie informacje potrzebne do użycia klas w pakiecie (lub klasie) są zawarte w pliku .class. Utworzenie osobnych plików nagłówkowych zawierających te same informacje wymagałoby powtórzenia ich w dwóch miejscach.


niestety często chcesz to powtórzyć - pomyśl o plikach WSDL, plikach IDL itp. Jeden opisuje interfejs, którego możesz użyć, a drugi plik zawiera implementację. Nagłówki C ++ są (słabymi) definicjami interfejsów.
gbjbaanb

6

W każdym języku - istnieją dwa etapy tworzenia ostatecznego kodu binarnego - kompilacja i łączenie (oczywiście jest ładowanie, ale tutaj nie ma to większego wpływu). Podczas kompilacji wystarczy umieścić haki (specyfikację funkcji, które zostaną wywołane) w odpowiednim miejscu. Linker faktycznie dołącza do nich, gdy dostępny jest zarówno prawdziwy kod. Jak dotąd nie ma różnicy między C ++ a Javą.

Konieczne jest jednak oddzielenie deklaracji i definicji w C ++. Jeśli trzymasz implementację w nagłówku i jeśli plik nagłówka się zmienia, kod, który jest z nim połączony, musi zostać ponownie skompilowany. Jeśli definicja znajduje się w osobnym pliku, kod wymaga jedynie ponownego połączenia.

Zrozum, że C ++ ma opcję statycznego łączenia, co oznacza, że ​​kod obiektu jest ustalony wraz z aplikacją wywołującą. Pamiętaj, że zarówno w C, jak i C ++, programowanie w pliku nagłówkowym, a nawet #include, nie jest niepoprawne. oznacza to tylko, że musisz niepokoić się, w jaki sposób odbywa się łączenie z tymi plikami obiektowymi.

Sytuacja w Javie jest zupełnie inna. Każdy plik klasy jest kompilowany z plikiem .class. Rzeczywiście, potrzeba kompilacji funkcji klasy wywołującej, która jest obsługiwana jako sekcja nagłówka w pliku .class. Jednak w Javie końcowe łączenie odbywa się tylko w środowisku wykonawczym (maszynie wirtualnej) tylko z podaną specyfikacją kodu bajtowego pliku klasy.

Zobacz to i to


4

Efektywnie interfejsy i obejmuje to nagłówki; dlatego definicje są identyczne z plikami binarnymi i nie mogą być niezsynchronizowane. Jest to jedna z najlepszych decyzji projektowych w Javie, ale niewielką irytacją jest to, że nie można połączyć tych deklaracji w celu uzyskania zwartości i spójności.


1

Jednym z dobrych powodów do tego jest oddzielenie kodu, który możesz chcieć ponownie wykorzystać (np. Typowe definicje) od kodu specyficznego dla danego projektu. Java chce, abyś określił tylko jedną klasę lub interfejs dla pliku, co w większości zmniejsza potrzebę dołączania nagłówków - ponieważ będziesz przeglądać udostępnione części już we własnych plikach.

Ponadto kompilatory i systemy kompilacji mogą chcieć buforować wstępnie skompilowane nagłówki, aby uniknąć ich analizowania więcej niż raz.


1
Przypuszczam, że można przechowywać interfejsy we wspólnym projekcie, a następnie wdrażać je w niezależnych projektach
Alexander Mills
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.