Apakah pengembangan Java biasanya melibatkan lebih banyak subkelas daripada C # /. NET?

34

Saya baru-baru ini mulai melihat pengembangan Android. Ini telah membawa saya kembali ke dunia pengembangan perangkat lunak Java. Terakhir kali saya bekerja dengan Java, saya akui, saya tidak memahami OOP sebanyak yang saya kira sekarang.

Karena sebagian besar menggunakan C # dalam karir saya, saya melihat perbedaan yang mengejutkan dalam bagaimana pewarisan digunakan Java dan C #.

Dalam C # sepertinya warisan dapat dihindari di sebagian besar situasi. Tugas yang dihadapi biasanya dapat diselesaikan dengan menggunakan kelas-kelas konkret dari kerangka NET .

Di Jawa, dari apa yang saya kumpulkan dari contoh kode, sepertinya kerangka Java memasok banyak antarmuka atau kelas abstrak yang kemudian dimaksudkan untuk diimplementasikan / diperluas oleh pengembang.

Ini sepertinya perbedaan yang terlalu besar untuk didasari pada gaya. Apa alasan di balik ini? Saya merasa seperti saya tidak akan menulis kode Java bersih sampai saya mengerti ini.

Juga, apakah ini terbatas hanya pada Android SDK atau apakah ini pendekatan Java-wide untuk OOP?

Atau dengan kata lain,

Ada apa dengan desain dua bahasa ini yang (tampaknya mendorong) lebih banyak atau lebih sedikit menggunakan warisan daripada yang lain?

Jika bahasa memperlakukan warisan secara identik, dan menganggap pengamatan saya valid, maka itu berarti ini terkait dengan desain kerangka / pustaka dan bukan bahasa. Apa yang akan menjadi motivasi untuk desain semacam ini?

MetaFight
sumber
1
Itu benar. Java memiliki terlalu banyak antarmuka. Saya ingin tahu mengapa perilaku pengembang ini umum untuk bahasa tertentu. Saya melihat ini terjadi lebih sering di proyek-proyek Jawa daripada yang lain. Harus ada alasan untuk ini dan bukan hanya pendapat.
Reactgular
1
@MathewFoscarini itu hanya pendapat Anda . Dalam proyek Java yang saya ikuti, pengembang cenderung menghindari warisan seperti wabah. Tidak ada yang berwibawa di sini, hanya pendapat saya . Ingin polling ?
agas
2
Anda, hampir, tidak perlu menurunkan satu kelas dari kelas lain di Jawa. Sebagai gantinya, Anda dapat mengimplementasikan antarmuka untuk mencapai polimorfisme dan mengimplementasikan objek yang dikomposisikan dan proksi pemanggilan metode untuk mencapai fungsionalitas yang di-shair.
DwB
1
@ BerpikirMedia Secara umum, Java dikalahkan dengan fanatik OSS. Prinsip-prinsip akademis adalah perhatian utama. Pengembang .Net adalah pragmatis yang peduli untuk menyelesaikan pekerjaan. Mereka menghargai kode kerja lebih dari kode terbersih.
Andy

Jawaban:

31

Ini sepertinya perbedaan yang terlalu besar untuk didasari pada gaya. Apa alasan di balik ini?

Pemahaman saya adalah bahwa hal itu sebagian besar adalah hanya keputusan gaya. Yah, mungkin bukan gaya, tapi idiom bahasa / lingkungan. Pengembang perpustakaan standar Java mengikuti satu set pedoman desain dan pengembang .NET yang lain (meskipun mereka memiliki kemampuan untuk melihat bagaimana pendekatan Java bekerja).

Ada sangat sedikit dalam bahasa aktual untuk mendorong atau menghalangi warisan. Hanya dua hal yang menurut saya relevan:

  1. .NET memperkenalkan generik lebih awal dalam masa hidupnya, sebelum terlalu banyak kode non-generik diimplementasikan. Alternatifnya adalah banyak inheritence untuk mengetik hal-hal yang dikhususkan.

  2. Perubahan yang lebih besar adalah delegasi yang didukung .NET. Di Jawa Anda terjebak dengan pewarisan (anonim) untuk menyediakan fungsionalitas variabel paling dasar. Ini mengarah ke perbedaan yang relatif besar dalam bagaimana kode dirancang untuk mengambil keuntungan dari delegasi atau untuk menghindari struktur warisan canggung yang diperlukan untuk melakukannya di Jawa.

Telastyn
sumber
3
Saya pikir jawaban ini menawarkan penjelasan yang sangat masuk akal. Terutama poin tentang pewarisan anonim sebagai pengganti delegasi. Saya telah mengamati ini banyak. Terima kasih.
MetaFight
3
Jangan lupa jenis anonim dan pohon sintaks / ekspresi lambda yang diperkenalkan di .NET 3.5. Dan tentu saja opt-in mengetik dinamis. NET 4. Ini hampir tidak diragukan lagi bahasa paradigma campuran sekarang, tidak sepenuhnya berorientasi objek.
Aaronaught
ya, dalam pengalaman saya menggunakan keduanya (termasuk pada proyek campuran di mana orang yang sama menggunakan kedua bahasa) orang cenderung lebih suka menggunakan sejumlah besar kelas yang lebih kecil ketika mengkode Jawa, sejumlah kecil kelas yang lebih besar (cenderung menuju kelas dewa) ketika menggunakan C #. Dengan sengaja membuat prototipe hal yang sama menggunakan gaya yang sama di keduanya, Anda berakhir dengan jumlah kelas yang sama (menggunakan kelas parsial, Anda mungkin akan berakhir dengan lebih banyak file kode bahkan ketika menggunakan C #).
jwenting
6

Ini adalah bahasa yang sangat berbeda, khususnya di bidang ini. Katakanlah Anda memiliki kelas. Dalam hal ini, kami akan menjadikannya kontrol pengguna, seperti kotak teks. Sebut saja UIControl. Sekarang kami ingin menempatkan ini di kelas lain. Dalam hal ini, karena kita menggunakan UI untuk contoh kita, kita akan menyebutnya kelas CleverPanel. Contoh CleverPanel kami ingin mengetahui tentang hal-hal yang terjadi pada instance UIControl-nya karena berbagai alasan. Bagaimana cara melakukannya?

Dalam C #, pendekatan dasar adalah untuk memeriksa berbagai Acara, menyiapkan metode yang akan dijalankan ketika setiap peristiwa menarik dipicu. Di Jawa, yang tidak memiliki peristiwa, solusi yang biasa adalah untuk melewatkan objek dengan berbagai metode penanganan "peristiwa" ke metode UIControl:

boolean  stillNeedIt =  ... ;
uiControl.whenSomethingHappens( new DoSomething()  {
    public void resized( Rectangle r )  { ... }
    public boolean canICloseNow()  { return !stillNeedIt; }
    public void closed()  { ... }
    ...
} );

Sejauh ini, perbedaan antara C # dan Java tidak mendalam. Namun, kami memiliki antarmuka DoSomething yang tidak diperlukan di C #. Juga, antarmuka ini mungkin mencakup banyak metode yang tidak dibutuhkan sebagian besar waktu. Dalam C #, kami hanya tidak menangani Peristiwa itu. Di Jawa, kami membuat kelas yang menyediakan implementasi nol untuk semua metode antarmuka, DoSomethingAdapter. Sekarang kita mengganti DoSomething dengan DoSomethingAdapter dan kita tidak perlu menulis metode apa pun untuk kompilasi yang bersih. Kami akhirnya hanya mengesampingkan metode yang kami butuhkan untuk membuat program bekerja dengan benar. Jadi kami akhirnya membutuhkan antarmuka dan menggunakan warisan di Jawa untuk mencocokkan apa yang kami lakukan dengan acara di C #.

Ini adalah contoh, bukan diskusi yang komprehensif, tetapi memberikan dasar mengapa ada begitu banyak warisan di Jawa dibandingkan dengan C #.

Sekarang, mengapa Java bekerja seperti ini? Fleksibilitas. Objek diteruskan ke saat Sesuatu yang Terjadi bisa saja diteruskan ke CleverPanel dari tempat lain sepenuhnya. Mungkin sesuatu yang beberapa contoh CleverPanel harus dilewatkan ke objek seperti UIControl untuk membantu objek CleverWindow di suatu tempat. Atau yang UIControl bisa menyerahkan pada salah satu nya komponen.

Selain itu, alih-alih adaptor mungkin ada implementasi DoSomething di suatu tempat yang memiliki ribuan baris kode di belakangnya. Kita bisa membuat contoh baru dari yang dan menyebarkannya. Kita mungkin perlu mengganti satu metode. Trik umum di Jawa adalah memiliki kelas besar dengan metode seperti:

public class BigClass implements DoSomething  {
    ...many long methods...
    protected int getDiameter()  { return 5; }
}

Kemudian di CleverlPanel:

uiControl.whenSomethingHappens( new BigClass()  {
    @Override
    public int getDiameter()  { return UIPanel.currentDiameter; }
} );

Platform Java open source melakukan banyak hal, yang cenderung mendorong programmer untuk berbuat lebih banyak - baik karena mereka mengikutinya sebagai contoh dan hanya untuk menggunakannya. Saya pikir desain dasar bahasa berada di belakang desain kerangka kerja Sun dan di belakang programmer Java menggunakan teknik ketika tidak menggunakan kerangka kerja.

Sangat mudah untuk membuat kelas dengan cepat di Jawa. Kelas, anonim atau bernama, hanya perlu dirujuk dalam satu blok kecil kode yang terkubur dalam-dalam dalam satu metode. Ini dapat dibuat benar-benar baru atau dengan sedikit modifikasi ke kelas yang sangat besar, yang sudah ada. (Dan kelas yang ada dapat menjadi tingkat atas di file sendiri, atau bersarang di kelas tingkat atas, atau hanya ditentukan dalam satu blok kode). Contoh kelas baru dapat memiliki akses penuh ke semua data objek yang menciptakan. Dan instance baru dapat dilewatkan dan digunakan di seluruh program, mewakili objek yang membuatnya.

(Sebagai tambahan, perhatikan bahwa penggunaan besar warisan di sini - seperti di tempat lain di Jawa - hanya untuk tujuan KERING. Ini memungkinkan kelas yang berbeda menggunakan kembali kode yang sama. Perhatikan juga kemudahan warisan di Jawa yang mendorong hal ini. )

Sekali lagi, ini bukan diskusi yang komprehensif; Saya hanya menggaruk permukaan di sini. Tapi ya, ada perbedaan yang mengejutkan dalam bagaimana pewarisan digunakan antara Java dan C #. Dalam hal ini, mereka adalah bahasa yang sangat berbeda. Itu bukan imajinasi Anda.

RalphChapin
sumber
Catatan: Anda dapat menghindari keharusan memberikan metode yang tidak melakukan apa-apa dengan memperluas kelas abstrak yang penuh dengan implementasi kosong. Dengan cara ini Anda dapat secara selektif menimpa metode yang melakukan sesuatu. Meskipun tidak seburuk itu, itu berarti tingkat warisan yang lain.
Peter Lawrey
-2

Sama sekali tidak ada perbedaan dalam cara penanganan warisan antara Java dan C #. Ketika Anda benar-benar akan menggunakan warisan atau komposisi adalah keputusan desain yang pasti dan sama sekali bukan sesuatu yang didorong atau dikecilkan oleh Java atau C #. Saya sarankan membaca artikel ini .

Semoga saya bisa membantu!

Pantelis Natsiavas
sumber
5
Anda berbicara tentang bahasa itu sendiri, tetapi saya pikir pertanyaannya adalah juga tentang perpustakaan dan penggunaan umum.
svick
3
Tapi ada yang kebiasaan di seluruh bahasa yang mendorong warisan ekstra di Jawa; lihat jawaban
RalphChapin