Java'da devralmayı yasaklamak için iyi nedenler vardır; örneğin, son sınıfları veya tek bir özel parametresiz kurucu kullanarak sınıfları kullanmak? Bir yöntemi kesinleştirmenin iyi nedenleri nelerdir?
Java'da devralmayı yasaklamak için iyi nedenler vardır; örneğin, son sınıfları veya tek bir özel parametresiz kurucu kullanarak sınıfları kullanmak? Bir yöntemi kesinleştirmenin iyi nedenleri nelerdir?
Yanıtlar:
Buradaki en iyi referansınız, Joshua Bloch'un "Miras için tasarım ve belge veya başka bir şeyi yasaklaması" adlı mükemmel kitabı "Etkili Java" nın 19. Maddesidir. (İkinci baskıdaki 17. madde ve birinci baskıdaki 15. madde.) Gerçekten okumalısınız, ama özetleyeceğim.
Eğer atadan miras alınacak şekilde tasarlanmamışsa, kalıtsal sınıfların ebeveynleri ile etkileşimi şaşırtıcı ve tahmin edilemez olabilir.
Bu nedenle sınıflar iki çeşit olmalıdır:
Genişletilmek üzere tasarlanmış sınıflar ve bunun nasıl yapılması gerektiğini açıklayan yeterli dokümantasyon
Sınıflar final olarak işaretlendi
Tamamen dahili bir kod yazıyorsanız, bu biraz fazla olabilir. Ancak, bir sınıf dosyasına beş karakter eklemek için gereken ekstra çaba çok azdır. Sadece iç tüketim için yazıyorsanız, gelecekteki bir kodlayıcı her zaman 'final'i kaldırabilir - bunu "bu sınıf kalıtım göz önünde bulundurularak tasarlanmadı" diyen bir uyarı olarak düşünebilirsiniz.
Bir yöntemi sonlandırmak isteyebilirsiniz, böylece sınıfların geçersiz kılınması diğer yöntemlerde güvenilen davranışı değiştiremez. Yapıcılarda çağrılan yöntemler genellikle nihai olarak bildirilir, böylece nesne oluştururken hoş olmayan sürprizler alamazsınız.
final
.
Bir sınıfı final yapmanın bir nedeni, kompozisyonu kalıtım üzerinde zorlamak istemeniz olabilir. Bu genellikle sınıflar arasında sıkı bağlantıdan kaçınmak için arzu edilir.
Nihai yöntemler için gidebileceğiniz 3 kullanım durumu vardır.
Bir dersi final yapma amacı:
Böylece hiçbir beden bu sınıfları genişletemez ve davranışlarını değiştiremez.
Örneğin: Wrapper sınıfı Integer son sınıftır. Bu sınıf son değilse, herhangi biri Integer'ı kendi sınıfına genişletebilir ve integer sınıfının temel davranışını değiştirebilir. Bundan kaçınmak için, java tüm sarmalayıcı sınıflarını son sınıf olarak yaptı.
DerivedInteger
, hala orijinal Integer sınıfını değiştirmediğini ve kullananların DerivedInteger
bunu kendi riski altında yaptıklarını, bu yüzden neden bir sorun olduğunu anlamıyorum.
değişmez nesneler yapmak isteyebilirsiniz ( http://en.wikipedia.org/wiki/Immutable_object ), bir singleton ( http://en.wikipedia.org/wiki/Singleton_pattern ) oluşturmak isteyebilirsiniz veya verimlilik, güvenlik veya güvenlik nedenleriyle birisinin yöntemi geçersiz kılmasını önlemek.
Kalıtım bir testere gibidir - çok güçlü, ancak yanlış ellerde korkunç. Ya miras alınacak bir sınıf tasarlarsınız (esnekliği sınırlayabilir ve çok daha uzun sürebilir) ya da onu yasaklamanız gerekir.
Etkili Java 2nd edition öğeleri 16 ve 17 veya blog yazım "Veraset Vergisi" bölümüne bakın .
Hmmm ... İki şey düşünebilirim:
Belirli güvenlik sorunlarıyla ilgilenen bir sınıfınız olabilir. Saldırgan, alt sınıfını ve alt sınıfını sisteminize besleyerek güvenlik kısıtlamalarını atlatabilir. Örneğin uygulamanız eklentileri destekleyebilir ve bir eklenti yalnızca güvenlikle ilgili sınıflarınızı alt sınıflara ayırabiliyorsa, bu hileyi bir şekilde alt sınıflı bir sürümünü yerine geçirmek için kullanabilir. Bununla birlikte, bu, Sun'ın küçük uygulamalar ve benzerleri ile uğraşması gereken bir şey, belki de gerçekçi bir durum değil.
Çok daha gerçekçi olanı bir nesnenin değişebilir hale gelmesini önlemektir. Örneğin, Dizeler değiştirilemez olduğundan, kodunuz ona referansları güvenle tutabilir
String blah = someOtherString;
önce dizeyi kopyalamak yerine. Ancak, String'i alt sınıflandırabiliyorsanız, dize değerinin değiştirilmesine izin veren yöntemler ekleyebilirsiniz, şimdi dize yalnızca yukarıdaki gibi kopyalarsa dizenin aynı kalacağına artık hiçbir kod güvenmeyecektir, bunun yerine dize.
Sınıfları ve yöntemleri son olarak işaretlerseniz, çalışma zamanının belirli bir nesneyi çağırmak için doğru sınıf yöntemini araması gerekmediğinden küçük bir performans artışı fark edebilirsiniz. Nihai olmayan yöntemler sanal olarak işaretlenir, böylece gerektiğinde uygun şekilde genişletilebilir, son yöntemler doğrudan sınıfta bağlanabilir veya satır içinde derlenebilir.
İnsanların kendilerini ve başkalarını karıştırabilecek şeyler yapmalarını engellemek. Bazı sabitleri veya hesaplamaları tanımladığınız bir fizik kütüphanesi düşünün. Son anahtar kelimeyi kullanmadan, birisi gelip ASLA değişmemesi gereken temel hesaplamaları veya sabitleri yeniden tanımlayabilir.
Sınıfları geçersiz kılmanın davranışını değiştirmemesi için bir yöntemi sonlandırmak istiyorsunuz. Davranışı değiştirmek istediğinizde yöntemi herkese açık hale getirin. Genel bir yöntemi geçersiz kıldığınızda değiştirilebilir.