Java geliştirme tipik olarak C # /. NET'ten daha fazla alt sınıflama içerir mi?


34

Geçenlerde Android gelişimine bakmaya başladım. Bu beni Java yazılım geliştirme dünyasına geri getirdi. Java ile en son çalıştığımda itiraf edeyim, neredeyse sandığım kadar OOP’u anlamadım.

Kariyerimde ağırlıklı olarak C # kullandıktan sonra, kalıtımın Java ve C # kullanımında şaşırtıcı bir fark görüyorum.

C # da çoğu durumda mirastan kaçınılabileceği görülüyordu. Eldeki görev genellikle .NET çerçevesinin somut sınıfları kullanılarak gerçekleştirilebilir .

Java'da, kod örneklerinden topladığım şeye göre, Java çerçevesi daha sonra geliştirici tarafından uygulanacak / genişletilecek birçok arayüz veya soyut sınıf sağlıyor.

Bu sadece stil kaynaması için çok büyük bir fark gibi görünüyor. Bunun arkasındaki sebep nedir? Bunu anlayana kadar temiz Java kodu yazamayacağımı hissediyorum.

Ayrıca, bu yalnızca Android SDK ile sınırlıdır veya bu, OOP için Java çapında bir yaklaşım mıdır?

Veya başka bir şekilde koymak,

Miras kullanımının diğerinden daha az ya da çok miras kullanması (cesaretlendirici görünüyor) tasarımıyla ilgili nedir?

Eğer diller mirasa aynı şekilde yaklaşırsa ve gözlemlerimin geçerli olduğunu varsayarsak, bunun dillerin değil çerçevelerin / kütüphanelerin tasarımı ile ilgili olduğu anlamına gelir. Bu tür bir tasarım için motivasyon ne olurdu?


1
Bu doğru. Java'nın çok fazla arayüzü var. Bu geliştirici davranışının neden belirli bir dil için ortak olduğunu bilmek isterim. Bunun Java projelerinde diğerlerinden daha sık olduğunu görüyorum. Bunun bir nedeni olmalı, sadece bir fikir değil.
Tepki

1
@MathewFoscarini bu sadece senin fikrin . Katıldığım Java projelerinde, geliştiriciler veba gibi kalıtımdan kaçınma eğilimindeydiler. Yetkili hiçbir şey yok, sadece benim görüşüm . Anket yapmak ister misin?
tatarcık

2
Java’da bir sınıfı diğerinden asla türetmeniz gerekmez. Bunun yerine, polimorfizm elde etmek için arayüzler uygulayabilir ve oluşturulmuş nesneler uygulayabilir ve yöntemin gölgeli işlevsellik elde etmek için çağırdığı proxy'leri uygulayabilirsiniz.
DwB

1
@ThinkingMedia Genel olarak, Java, OSS zealotları / purists ile istila edilir. Akademik ilkeler en önemli endişe kaynağıdır. Net geliştiricileri, işi yapmak konusunda endişeli olan pragmatistler. Çalışma koduna en temiz koddan daha çok değer veriyorlar.
Andy

Yanıtlar:


31

Bu sadece stil kaynaması için çok büyük bir fark gibi görünüyor. Bunun arkasındaki sebep nedir?

Benim anlayış büyük ölçüde olmasıdır olduğunu basitçe bir üslup karar. Belki de stil değil, dilin / çevrenin deyimleri. Java standart kütüphane geliştiricileri, bir dizi tasarım kuralını ve .NET geliştiricisini bir başkasını takip etti (Java'nın yaklaşımının nasıl çalıştığını görebilme yeteneğine sahip olsalar da).

Gerçek dilde kalıtımı teşvik etmek veya caydırmak için çok az şey vardır. Sadece iki şey beni ilgilendiren etkiliyor:

  1. .NET, jenerik ürünleri çok daha fazla jenerik olmayan kod uygulanmadan önce yaşamları boyunca tanıttı. Alternatif, uzmanlaşma türlerini yazmak için çok fazla mirastır.

  2. Daha büyük bir değişiklik, .NET tarafından desteklenen delegelerdi. Java'da, değişken işlevlerin en temelini sağlamak için (anonim) miras kalmışsınız. Bu, kodun delegelerin avantajlarından yararlanmak veya Java'da yapmak için gereken garip miras yapılarını önlemek için tasarlanma biçiminde nispeten büyük bir fark yaratmaktadır.


3
Bence bu cevap çok makul bir açıklama sunuyor. Özellikle delegeler yerine isimsiz miras konusu. Bunu çok gözlemledim. Teşekkürler.
MetaFight

3
.NET 3.5'te tanıtılan adsız türleri ve lambda sözdizimi / ifade ağaçlarını unutmayın. Ve tabii ki .NET 4'te dinamik yazma işlemine katılmayı tercih edin. Neredeyse kuşkusuz karışık bir paradigma dili, kesinlikle nesne yönelimli değil.
Aaron

evet, deneyimlerime göre ikisini de kullandım (aynı kişilerin her iki dili de kullandığı karma projeler dahil) insanlar Java'yı kodlarken daha fazla sayıda küçük sınıf kullanmayı tercih ederler; C # kullanarak. Her ikisinde de aynı stili kullanarak aynı şeyi kasten prototip hale getirdikten sonra, benzer sayıda sınıfa (kısmi sınıfları kullanarak, C # kullanırken bile daha fazla kod dosyasına sahip olursunuz) bitirdiniz.
14'te

6

Bunlar, özellikle bu alanda çok farklı dillerdir. Diyelim ki bir sınıfınız var. Bu durumda, onu bir metin kutusu gibi bir kullanıcı kontrolü yapalım. UIControl olarak adlandırın. Şimdi bunu başka bir sınıfa koymak istiyoruz. Bu durumda, örneğimiz için bir UI kullandığımız için bunu CleverPanel sınıfı olarak adlandıracağız. CleverPanel örneğimiz, UIControl örneğinde gerçekleşen olayları çeşitli nedenlerle bilmek isteyecektir. Bu nasıl yapılır?

C # 'da, temel yaklaşım, her bir ilginç olay tetiklendiğinde uygulanacak yöntemleri ayarlayarak çeşitli Olayları kontrol etmektir. Olaylardan yoksun olan Java'da olağan çözüm, çeşitli "olay" işleme yöntemlerine sahip bir nesneyi bir UIControl yöntemine iletmektir:

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

Şimdiye kadar, C # ve Java arasındaki fark derin değil. Bununla birlikte, C # 'da gerekli olmayan DoSomething arayüzüne sahibiz. Ayrıca, bu arayüz çoğu zaman ihtiyaç duyulmayan birçok yöntem içerebilir. C # 'da, biz sadece bu olayla ilgilenmiyoruz. Java'da, tüm arayüz yöntemleri, DoSomethingAdapter için boş bir uygulama sağlayan bir sınıf oluşturuyoruz. Şimdi DoSomething'i DoSomethingAdapter ile değiştiriyoruz ve temiz bir derleme için hiçbir yöntem yazmamız gerekmiyor. Programın doğru çalışması için ihtiyaç duyduğumuz yöntemleri geçersiz kılıyoruz. Bu yüzden bir arayüze ihtiyacımız var ve Java # 'da miras kullanarak C # olaylarıyla yaptığımız şeyle eşleşiyoruz.

Bu bir örnek, kapsamlı bir tartışma değil, fakat Java'da C # ile karşılaştırıldığında neden bu kadar kalıtımsallık olduğunun temellerini veriyor.

Şimdi, Java neden bu şekilde çalışıyor? Esneklik. Nesne, SomethingHappens'in CleverPanel'e başka bir yerden tamamen geçilmiş olabileceği zamana geçti. Bir CleverPanel örneğinin bir yerde bir CleverWindow nesnesine yardımcı olmak için UIControl benzeri nesnelerine iletmesi gereken bir şey olabilir. Veya UIControl birine bunu bırakabileceğini söyledi onun bileşenleri.

Ayrıca, bir adaptör yerine, arkasında binlerce kod satırı bulunan bir DoSomething uygulaması olabilir. Biz yeni bir örneğini oluşturabilir o ve onu geçmektedir. Bir yöntemi geçersiz kılmamız gerekebilir. Java'daki yaygın bir püf noktası, şöyle bir yöntemle büyük bir sınıfa sahip olmaktır:

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

Sonra CleverlPanel'de:

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

Açık kaynak kodlu Java Platformu, programcıları daha fazlasını yapmaya itme eğiliminde olan bir çok şey yapıyor; çünkü her ikisi de bunu örnek olarak ve basitçe kullanmak için takip ediyorlar. Ben dilinin temel tasarım Sun'ın çerçeve tasarımı arkasında olduğunu düşünüyorsunuz ve ne zaman Java programcısı en tekniklerini kullanarak arkasında değil çerçevesini kullanarak.

Java anında anında bir sınıf oluşturmak çok kolaydır. Adsız veya adlandırılmış sınıfa yalnızca tek bir yöntemde gömülü olan küçük bir kod bloğunda başvurulabilir. Tamamen yeni veya çok büyük, mevcut bir sınıfa hafif değişiklikler yaparak yaratılabilir. (Ve varolan sınıf kendi dosyasında üst düzey olabilir veya üst düzey bir sınıfta yer alabilir veya yalnızca tek bir kod bloğunda tanımlanabilir). Yeni sınıf örneği, oluşturulan tüm nesnenin verilerine tam erişebilir. Ve yeni örnek, onu yaratan nesneyi temsil ederek programın her tarafında geçirilebilir ve kullanılabilir.

(Bir kenara, burada kalıtımın büyük bir kullanımının - Java'nın diğer yerlerinde olduğu gibi - sadece DRY amaçları için olduğunu unutmayın. Farklı sınıfların aynı kodu yeniden kullanmalarına izin verir. Ayrıca, Java'da kalıtım kolaylığı olduğunu da unutmayın. )

Yine, bu kapsamlı bir tartışma değil; Sadece buradaki yüzeyi çiziyorum. Ancak evet, Java ve C # arasında kalıtımın nasıl kullanıldığı konusunda şaşırtıcı bir fark var. Onlar bu açıdan çok farklı dillerdir. Bu senin hayal gücün değil.


Not: Soyut uygulamaları boş uygulamalarla genişleterek, hiçbir şey içermeyen yöntemler sağlamaktan kaçınabilirsiniz. Bu yolla, bir şeyi yapan yöntemleri seçici olarak geçersiz kılabilirsiniz. Çirkin olmasa da, başka bir kalıtım düzeyi anlamına gelir.
Peter Lawrey

-2

Kalıtımın Java ile C # arasında ele alınmasında kesinlikle bir fark yoktur. Gerçekten miras veya kompozisyon kullanacağınız zaman kesinlikle bir tasarım kararıdır ve hiçbir şekilde Java veya C # 'nın cesaretlendirdiği veya caydırdığı bir şey değildir. Lütfen bu makaleyi okumanızı tavsiye ederim .

Umarım yardım ettim!


5
Dillerin kendileri hakkında konuşuyorsunuz, ancak sorunun kütüphaneler ve ortak kullanım ile ilgili olduğunu düşünüyorum.
svick

3
Ama olan Java ekstra mirasını teşvik dilin geri kalanında tuhaflıklar; RalphChapin'in cevabını görün
Izkata
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.