Java, C ++ gibi sınıf tanımları ve uygulamaları arasında bir ayrımı teşvik ediyor mu?


10

Bir ev ödevim var ve GRASP "Korumalı Varyasyon" a göre hangi yaklaşımın daha iyi olduğunu değerlendirmem gerekiyor. Stack Overflow hakkında üstbilgi ve kod dosyaları C ++ ayrılması hakkında bir soru buldum .

Ancak, Java neden sınıf tanımları ve sınıf uygulamaları arasındaki ayrımı teşvik C ++ izlemiyor bilmek istiyorum. Java yöntemi ile C ++ yöntemi üzerinde herhangi bir avantajı var mı?


"Java neden başlık dosyalarını kullanmıyor?" Bunun (veya en azından yakından ilişkili soruların) daha önce gündeme getirildiğinden oldukça eminim.

Hata! Bağlantı çalışmadı. Temel olarak bilmek istediğim şey, her ikisi arasında ve kodun yeniden kullanılması veya genişletilebilirlik için daha kolay olma eğilimi arasındaki farkları yeniden biçimlendireceğim.
Etienne Noël

1
C'nin (ve C ++ uzantısıyla), C'nin oluşturulduğu sırada sınırlı tek geçişli derleyici teknolojisi nedeniyle başlık dosyalarını uygulama dosyalarından ayırmaktan başka seçeneği yoktu.
Kanal72

2
Java, söz konusu sınıf arabirimi uygularsa sınıf tanımını ve sınıf uygulamasını ayırabilen Arabirimler içerebilir. Yine de C ++ ile aynı değil.
SinirliWithFormsDesigner

1
Ayrıca, P ++PL deyimini kullanmadığınız sürece, C ++ başlık dosyaları benden daha fazla uygulama gösterir. Olsa bile private, tüm veri üyelerini listelemek gerekir , böylece uygulama boyutu bilecek ve privateüye de işlev görecektir .
David Thornley

Yanıtlar:


13

Aşağıdaki programda kaç satır kod var?

#include <iostream>

int main()
{
   std::cout << "Hello, world!\n";
   return 0;
}

Muhtemelen 7 (veya boş satırı saymadıysanız 6 veya parantezleri saymadıysanız 4) yanıtladınız.

Ancak derleyiciniz çok farklı bir şey görüyor:

~$ cpp hello.cpp | wc
  18736   40822  437015

Evet, bu 18.7 KLOC sadece "Merhaba dünya!" programı. C ++ derleyicisi tüm bunları ayrıştırmak zorundadır . Bu, C ++ derlemesinin diğer dillerle karşılaştırıldığında çok uzun sürmesinin ve modern dillerin başlık dosyalarından kaçınmasının önemli bir nedenidir .

Daha iyi bir soru

Neden gelmez C başlık dosyaları var ++?

C ++, C'nin bir üst kümesi olacak şekilde tasarlanmıştır, bu nedenle başlık dosyalarını geriye dönük uyumluluk için saklamak zorunda kaldı.

Tamam, neden C'nin başlık dosyaları var?

İlkel ayrı derleme modeli nedeniyle. C derleyicileri tarafından oluşturulan nesne dosyaları hiçbir tür bilgisi içermez, bu nedenle tür hatalarını önlemek için bu bilgileri kaynak kodunuza eklemeniz gerekir.

~$ cat sqrtdemo.c 
int main(void)
{
    /* implicit declaration int sqrt(int) */
    double sqrt2 = sqrt(2);
    printf("%f\n", sqrt2);
    return 0;
}

~$ gcc -Wall -ansi -lm -Dsqrt= sqrtdemo.c
sqrtdemo.c: In function main’:
sqrtdemo.c:5:5: warning: implicit declaration of function printf [-Wimplicit-function-declaration]
sqrtdemo.c:5:5: warning: incompatible implicit declaration of built-in function printf [enabled by default]
~$ ./a.out 
2.000000

Uygun tür bildirimlerini eklemek hatayı düzeltir:

~$ cat sqrtdemo.c 
#undef printf
#undef sqrt

int printf(const char*, ...);
double sqrt(double);

int main(void)
{
    double sqrt2 = sqrt(2);
    printf("%f\n", sqrt2);
    return 0;
}

~$ gcc -Wall -ansi -lm sqrtdemo.c
~$ ./a.out 
1.414214

Hiçbir #includes olmadığına dikkat edin . Ancak çok sayıda harici işlev kullandığınızda (çoğu program bunu yapar), bunları manuel olarak bildirmek sıkıcı ve hataya açık hale gelir. Başlık dosyalarını kullanmak çok daha kolay.

Modern diller başlık dosyalarından nasıl kaçınabilir?

Tür bilgisi içeren farklı bir nesne dosyası biçimi kullanarak. Örneğin, Java * .class dosya biçimi , alan türlerini ve yöntem parametrelerini belirten "tanımlayıcıları" içerir.

Bu yeni bir buluş değildi. Daha önce (1987), Borland Turbo Pascal 4.0'a ayrı olarak derlenmiş "birimler" eklediğinde , başlık dosyalarına olan ihtiyacı ortadan kaldırmak için *.TPUTurbo C'ler yerine yeni bir biçim kullanmayı seçti *.OBJ.


İlginç olsa da, Turbo Pascal'ı s OBJyerine dosya çıktısı olarak ayarlayabileceğinizden oldukça eminim TPU...
CV33

7

Java, bir sözleşme tanımlamak için arayüzlere sahiptir. Bu, arayan kişinin ihtiyaç duyduğu şeyden ve gerçek uygulamadan daha yüksek bir soyutlama düzeyi sağlar. yani arayan kişinin uygulayıcı sınıfı bilmesi gerekmez, yalnızca desteklediği sözleşmeyi bilmesi gerekir.

Bir Haritadaki tüm anahtar / değerleri yavaşlatan bir yöntem yazmak istediğinizi varsayalım.

public static <K,V> void printMap(Map<K,V> map) {
    for(Entry<K,V> entry: map.entrySet())
        System.out.println(entry);
}

Bu yöntem, girişi uygulayan sınıftan kaldırılan soyut bir arabirimde entrySet () yöntemini çağırabilir. Bu yöntemi ile çağırabilirsiniz.

printMap(new TreeMap());
printMap(new LinkedHashMap());
printMap(new ConcurrentHashMap());
printMap(new ConcurrentSkipListMap());

1
Orada Programcılar hoş geldiniz Peter - :-) adını tanıdığımı düşündüm. Bazı kişilerin Java'daki Abstract temel sınıflarının da bir sözleşme tanımladığını iddia edeceğini ekleyeceğim - ancak bu muhtemelen ayrı bir iş parçacığı için bir argüman.
Martijn Verburg

Merhaba @MartijnVerburg, Güzel bir ek. Soyut sınıfların, uygulamalar olmadan arayüzler ile somut sınıflar arasındaki farkı bulanıklaştırdığını düşünüyorum. Genişletme yöntemleri ayrımı daha da bulanıklaştıracaktır. Daha basit oldukları için bir arayüz kullanmayı tercih ederim.
Peter Lawrey

Evet Java, bir kamu sözleşmesi tanımlamak için birden fazla yolu olan Scala yolunda ilerlemeye başlayacak - Bunun iyi bir şey olup olmadığından emin değilim :-)
Martijn Verburg

-1 Bu basit bir C ++ ile de mümkündür #define interface class.
Sjoerd

@Sjoerd C ++ yöntemlerinin artık virtualpolimorfizm elde etmek için anahtar kelimeyi kullanmasına gerek olmadığını bilmiyordum ve Java'da olduğu gibi yalnızca bir veya iki beton türü kullanırsanız, bu durum hiçbir performans cezasına sahip değildir. Bana bunun C ++ ile nasıl çalıştığına dair herhangi bir belgeye işaret edebilir misiniz?
Peter Lawrey

5

Başlıklar açıkçası tarihi bir kaza olarak var. Bu inanılmaz derecede zayıf bir sistem, başka hiçbir dilde bu kadar korkunç bir şey yok ve onlarla uğraşmak zorunda olmayan herkes sevinmeli.


3

Üstbilgiler ayrı derlemeyi etkinleştirmek için vardır. # Başlıkları ekleyerek, derleyicinin derlenmiş C ++ kodunun ikili yapısı hakkında hiçbir şey bilmesine gerek yoktur ve bu işi ayrı bir bağlayıcıya bırakabilir. Java, derleyicisiyle ayrı bir bağlayıcı kullanmaz ve .class dosyaları kesin olarak tanımlandığından, derleyici, her derleme biriminde yeniden bildirmeye gerek kalmadan tüm üyelerini tüm türleriyle belirlemek için okuyabilir.

Tüm uygulamayı bir C ++ başlığına dahil edebilirsiniz, ancak derleyicinin #inc her eklendiğinde yeniden derlemesine neden olarak, bağlayıcıyı yinelenen kopyaları sıralamaya ve atmaya zorlar.


0

Java, sınıf tanımının ve uygulamasının ayrılmasını teşvik eder, sadece nereden baktığınıza bağlıdır.

Bir Java sınıfının yazarı olduğunuzda, sınıfın tanımını ve uygulanmasını tek bir dosyada görebilirsiniz. Sınıfı korumak için tek bir yere gittiğiniz için geliştirme sürecini basitleştirir, iki dosya (C ++ 'da yaptığınız gibi .h ve .cpp) arasında geçiş yapmanız gerekmez. Ancak, sınıfın tüketicisi olduğunuzda, tanımla yalnızca bir .jar veya bağımsız bir .class içinde paketlenmiş bir .class dosyası aracılığıyla ilgilenirsiniz.

C ++, tanımı ve uygulamayı ayırmanıza izin verir, ancak bu ad-hoc. Örneğin, yöntemi başlık dosyasında satır içine yazmanızı engelleyecek bir şey yoktur ve şablon sınıfları için bu zorunludur. Üstbilgi dosyası ayrıca, sınıfın bir uygulama ayrıntısı ve bir tüketici ile ilgisi olmasa da üstbilgi dosyasına bakan herkes tarafından görülebilen üye değişkenleri de listeler.

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.