Özellik olarak Java 8 varsayılan yöntemleri: güvenli mi?


116

Java 8'de özelliklerin fakirlerin erkek versiyonu olarak varsayılan yöntemleri kullanmak güvenli bir uygulama mı?

Bazıları pandaları sadece uğruna kullanırsanız üzüleceğini iddia ediyor , çünkü bu harika, ama niyetim bu değil. Ayrıca, varsayılan yöntemlerin API evrimini ve geriye dönük uyumluluğu desteklemek için tanıtıldığı da sık sık hatırlatılır, ki bu doğrudur, ancak bu onları kendi başına özellikler olarak kullanmayı yanlış veya çarpıtmaz yapmaz.

Ben şu pratik kullanım durumunda akılda:

public interface Loggable {
    default Logger logger() {
        return LoggerFactory.getLogger(this.getClass());
    }
}

Ya da belki bir tanımlayın PeriodTrait:

public interface PeriodeTrait {
    Date getStartDate();
    Date getEndDate();
    default isValid(Date atDate) {
        ...
    }
}

Kabul edilebilir bir şekilde, kompozisyon (hatta yardımcı sınıflar) kullanılabilir, ancak daha ayrıntılı ve dağınık görünür ve polimorfizmden yararlanmaya izin vermez.

Öyleyse, varsayılan yöntemleri temel özellikler olarak kullanmak uygun / güvenli mi yoksa öngörülemeyen yan etkiler konusunda endişelenmeli miyim?

SO ile ilgili birkaç soru Java ve Scala özellikleriyle ilgilidir; buradaki nokta bu değil. Ben de sadece fikir istemiyorum. Bunun yerine, yetkili bir cevap veya en azından alan bilgisi arıyorum: kurumsal projenizde özellikler olarak varsayılan yöntemleri kullandıysanız, bunun bir zaman bombası olduğu ortaya çıktı mı?


Bana öyle geliyor ki, soyut bir sınıfı miras almakla aynı faydaları elde edebilirsiniz ve pandaları ağlatmak konusunda endişelenmenize gerek kalmaz ... Bir Arayüzde varsayılan bir yöntemi kullanmamın tek nedeni, işlevselliğe ihtiyacınız olması ve yapamamanızdır. Arayüze dayalı bir grup eski kodu değiştirin.
Deven Phillips

1
@ İnfosec812'ye kendi statik günlükçü alanını tanımlayan soyut bir sınıfın genişletilmesi konusunda katılıyorum. Logger () yönteminiz her çağrıldığında yeni bir günlükçü örneği oluşturmaz mı?
Eidan Spiegel

Günlük kaydı için, Projectlombok.org'a ve @ Slf4j ek açıklamalarına bakmak isteyebilirsiniz.
Deven Phillips

Yanıtlar:


120

Kısa cevap: eğer onları güvenle kullanırsanız güvenlidir :)

Snarky cevap: söyle sen özelliklerin demek ve belki Sana daha iyi bir cevap vereceğiz :)

Tüm ciddiyetle, "özellik" terimi iyi tanımlanmamıştır. Çoğu Java geliştiricisi, Scala'da ifade edildiği şekliyle özelliklere en çok aşinadır, ancak Scala, isim veya fiili olarak niteliklere sahip ilk dilden uzaktır.

Örneğin, Scala'da özellikler durum bilgilidir ( vardeğişkenlere sahip olabilir ); Fortress'te saf davranışlardır. Java'nın varsayılan yöntemlere sahip arabirimleri durumsuzdur; bu onların özellik olmadığı anlamına mı geliyor? (İpucu: bu hileli bir soruydu.)

Yine Scala'da özellikler doğrusallaştırma yoluyla oluşturulur; sınıf eğer Aözellikleri uzanır Xve Y, hangi ardından sırası Xile Yarasındaki çatışmaları nasıl belirler karıştırılır Xve Yçözülür. Java'da, bu doğrusallaştırma mekanizması mevcut değildir (kısmen "Java'ya benzemediği için reddedilmiştir.)

Arayüzlere varsayılan yöntemler eklemenin en yakın nedeni arayüz gelişimini desteklemekti , ancak bunun ötesine geçtiğimizin de farkındaydık. Bunun "arayüz evrimi ++" veya "özellikler -" olduğunu düşünmeniz, kişisel bir yorumlama meselesidir. Bu nedenle, güvenlik hakkındaki sorunuza cevap vermek için ... mekanizmanın desteklemediği bir şeye isteyerek esnetmeye çalışmak yerine, aslında neyi desteklediğine bağlı kaldığınız sürece, iyi olmalısınız.

Temel tasarım hedeflerinden biri , bir arayüzün istemcisinin bakış açısından , varsayılan yöntemlerin "normal" arayüz yöntemlerinden ayırt edilemez olması gerektiğiydi. Bir yöntemin öntanımlılığı, bu nedenle, sadece arayüzün tasarımcısı ve uygulayıcısı için ilginçtir .

Tasarım hedeflerine uygun olan bazı kullanım durumları şunlardır:

  • Arayüz gelişimi. Burada, mevcut bir arayüze, o arayüzdeki mevcut metotlar açısından mantıklı bir varsayılan uygulamaya sahip olan yeni bir metot ekliyoruz. Bir örnek , varsayılan uygulamanın yöntem açısından yazıldığı forEachyöntemin eklenmesi olabilir . Collectioniterator()

  • "İsteğe bağlı" yöntemler. Burada, bir arayüzün tasarımcısı, "Uygulayıcıların, gerektirdiği işlevsellik sınırlamalarıyla yaşamak istiyorlarsa, bu yöntemi uygulamalarına gerek yoktur" diyor. Örneğin, Iterator.removeatan bir varsayılan verildi UnsupportedOperationException; uygulamalarının büyük çoğunluğu Iteratorzaten bu davranışa sahip olduğundan, varsayılan yöntem bu yöntemi esasen isteğe bağlı kılar. (Davranış AbstractCollectionvarsayılan olarak ifade edilmişse, Collectionaynı şeyi mutatif yöntemler için yapabiliriz.)

  • Kolaylık yöntemleri. Bunlar, kesinlikle kolaylık sağlamak için olan, yine genellikle sınıfta varsayılan olmayan yöntemler açısından uygulanan yöntemlerdir. logger()İlk örnekteki yöntem bu makul bir resmidir.

  • Combinators. Bunlar, mevcut örneğe dayalı olarak arabirimin yeni örneklerini somutlaştıran bileşimsel yöntemlerdir. Örneğin, yöntemler Predicate.and()veya Comparator.thenComparing()birleştiricilerin örnekleridir.

Varsayılan bir uygulama sağlarsanız, @implSpecuygulayıcıların yöntemi geçersiz kılmak isteyip istemediklerini anlamalarına yardımcı olmak için varsayılan için bazı belirtimler de sağlamalısınız (JDK'da bunun için javadoc etiketini kullanıyoruz ). Kolaylık yöntemleri ve birleştiriciler gibi bazı varsayılanlar neredeyse hiçbir zaman geçersiz kılınmaz; diğerleri, isteğe bağlı yöntemler gibi, genellikle geçersiz kılınır. Varsayılanın ne yapmayı vaat ettiği hakkında yeterli spesifikasyon (yalnızca dokümantasyon değil) sağlamanız gerekir, böylece uygulayıcı bunu geçersiz kılmak gerekip gerekmediğine dair mantıklı bir karar verebilir.


9
Bu kapsamlı cevap için teşekkürler Brian. Şimdi hafif bir yürekle varsayılan yöntemleri kullanabilirim. Okuyucular: Brian Goetz'den arayüz gelişimi ve varsayılan yöntemler hakkında daha fazla bilgi, örneğin NightHacking Worldwide Lambdas'ta bulunabilir .
youri

Teşekkürler @ brian-goetz. Söylediklerinize göre, Java'nın varsayılan yöntemlerinin Ducasse ve diğerleri makalesinde ( scg.unibe.ch/archive/papers/Duca06bTOPLASTraits.pdf ) tanımlanan geleneksel özellikler kavramına daha yakın olduğunu düşünüyorum . Scala "özellikleri" bana hiç bir özellik gibi görünmüyor, çünkü durumları var, kompozisyonlarında doğrusallaştırma kullanıyorlar ve aynı zamanda yöntem çatışmalarını da örtük olarak çözüyor gibi görünüyorlar - ve bunların hepsi geleneksel özelliklerin yapmadığı şeyler. Sahip olmak. Aslında, Scala özelliklerinin özelliklerden çok mikslere benzediğini söyleyebilirim. Ne düşünüyorsun? Not: Hiç Scala'da kodlamadım.
adino

Dinleyici görevi gören bir arabirimdeki yöntemler için boş varsayılan uygulamaları kullanmaya ne dersiniz? Dinleyici uygulaması, yalnızca birkaç arayüz yöntemini dinlemekle ilgilenebilir, bu nedenle, yöntemleri varsayılan hale getirerek, uygulayıcı yalnızca dinlemesi gereken yöntemleri uygulamak zorundadır.
Lahiru Chandima

1
@LahiruChandima gibi MouseListenermi? Bu API stilinin mantıklı olduğu ölçüde, bu "isteğe bağlı yöntemler" grubuna uymaktadır. İsteğe bağlılığı açıkça belgelediğinizden emin olun!
Brian Goetz

Evet. Tıpkı olduğu gibi MouseListener. Cevabınız için teşekkürler.
Lahiru Chandima
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.