Arayüzleri kim genişletir? Ve neden?


20

AFAIK, sınıf extendsana sınıflarım ve implementsarayüzlerim. Ama kullanamayacağım bir durumla karşılaşıyorum implements SomeInterface. Genel türlerin beyanıdır. Örneğin:

public interface CallsForGrow {...}

public class GrowingArrayList <T implements CallsForGrow>  // BAD, won't work!
                              extends ArrayList<T> 

Burada implementssözdizimi kullanmak yasaktır. İlk önce, <> içindeki arayüzü kullanmak hiç yasak değil, ama hayır diye düşündüm. Mümkün, sadece extendsyerine kullanmak zorundayım implements. Sonuç olarak, bir arabirimi "genişletiyorum". Bu başka bir örnek işe yarıyor:

public interface CallsForGrow {...}

public class GrowingArrayList <T extends CallsForGrow>  // this works!
                              extends ArrayList<T> 

Bana göre sözdizimsel bir tutarsızlık gibi görünüyor. Ama belki Java 6'nın bazı inceliklerini anlamıyorum? Arabirimleri genişletmem gereken başka yerler var mı? Uzatmak istediğim arayüz bazı özel özelliklere sahip olmalı mı?

Yanıtlar:


25

Genel tür değişkenleri durumunda derleyici aslında Tbir sınıf, arayüz, numaralandırma veya ek açıklama olup olmadığını umursamaz . Tek umurunda verilen alt ve süper tipler içeren bir tip olması.

Ve sözdizimini karmaşıklaştırmak için bir neden yoktur, çünkü başka bir yerde (aslında bir arayüz uyguladığınız yerde) sınıflar ve arayüzler arasındaki ayrım önemlidir (örneğin, implementbir arayüzünüz varsa , tanımladığı tüm yöntemleri uygulamanız gerekir, ancak yapmak eğer, gerek extend) bir (non-soyut) sınıfı.

Bir anlığına implementsburaya yazmanız gerektiğini varsayarsak , enumdeğerler (yalnızca yazmak yerine <E extends Enum<E>>) ve ek açıklamalar (kullanarak kolayca beyan edebileceğiniz) için ayrı bir sözdizimine de ihtiyacınız olacaktır <A extends Annotation>.

Eğer tek yer ihtiyaç yazma için implementsaslında arabirimini uygulamak noktasında. At o noktada (ve nokta sadece o) Eğer arabirimde tanımlanan yöntemler uygulamak gerekir çünkü fark önemlidir. Diğer herkes için, verilen herhangi Abir temel sınıf veya uygulanan bir arayüz olup olmadığı önemli değildir B: süper tiptir ve önemli olan budur.

Ayrıca extends, arabirimlerle birlikte kullandığınız bir yer daha olduğunu unutmayın :

interface A {
}

interface B extends A {
}

Bu noktada implementsyanlış olur, çünkü B uygulamaz A .


Mantıklarınızı kullanacaksak , sadece jeneriklerde değil, her zaman 'ExtInface'yi genişletir' kullanmalıyız .
Gangnus

2
@Gangnus: hayır, çünkü uygulayıcı için somut bir fark var extendsve implementssadece konuya saf bir tip sistemi perspektifinden bakarken, hiçbir fark yok.
Joachim Sauer

1
Üzgünüm, düşüncelerini anlamıyorum. --1. Neden bir durumda "saf bir tip sistem perspektifi" kullanmalıyız, diğerinde değil? --2. Sözdizimsel talepler neden bu farklı yerlerde değişiyor? Açıklayabilir misiniz, lütfen. Cevapta, mümkünse.
Gangnus

1
@Gangnus: Tbunun bir sınıf olduğunu kim söyledi ? Tbir arabirim türüne veya enumtürüne başvurabilir.
Joachim Sauer

1
C # 'dan gelen tüm tartışma saçma. bir türün süper tiplerini belirtiriz :. ve örtülerin altında, bir arayüz, abstractbirden fazla kalıtsallığa izin vermek için , yalnızca eklenmemiş sanal ( ) üyelerin bulunduğu kısıtlama ile her zaman soyut bir sınıftır ve olmuştur . arasında bir fark anlamıyla yoktur implementsve extends. her ikisi de aynı kelimeyle ( extends) veya rastgele bir sembolle ( :) değiştirilebilir ve hiçbir şey kaybolmaz.
sara

5

Java 5 ve özellikle de jenerikler başlangıçta bir ilgi kaydeden geliştiricilere sunulduğunda sözdizimi oldukça farklıydı. Yerine Set<? extends Foo>ve Set<? super Bar>o vardı Set<+Foo>ve Set<-Foo>. Ancak, geri bildirim daha spesifik veya daha geniş (daha fazla sınıf)+ anlamına gelmediğinin açık olmamasıydı . Sun bu geri bildirime sözdizimini değiştirerek yanıt verdi, ancak geriye dönük uyumluluk için sorun olabilecek yeni anahtar kelimeler getirmeme kısıtlaması dahilinde.

Sonuç, ikisinin de oldukça doğal olmamasıdır. Gözlemlediğiniz gibi, extendsdiğer bağlamlarda kullanılan dil olmayan sınıfları "genişleten" arabirimlerden bahsetmek aşırı yüklendi; ve superdaha önce bir üst sınıf atıfta anahtar kelime, yani ifade ilişkinin ters yönde olan "bir üst sınıf bir" anlamına gelir, aşırı.

Bununla birlikte, bir arayüzün ne olduğunun temelleri bu değişiklikten etkilenmez ve yeni bir şekilde genişletilen özel arayüzler sunmaz.


+1. Anlıyorum ve kabul ediyorum. Ancak Joachim Sauer, T'nin mutlaka bir sınıf olduğunu düşündüğüm hatalı düşüncemi buldu. Yani, cevap onun. Anlayışınız bir (veya 2) kat daha yüksektir :-). Benim sorunum daha ilkeldi. Yine de gelişimim için teşekkürler.
Gangnus

2

Bu sözdizimine izin vermenin ve yasaklamanın dezavantajları vardır ve izin verenler çok daha büyüktür.

Sadece düşün.

Arayüz ve uygulamanın ayrılması temel programlama deyimlerinden biridir. Bu nedenle, "arayüz bir şey uygular" yazımına izin veren sözdizimi , işlenenlerin çoğalmasını göstermek için artı işaretini kullanan kadar kötü olur .


Tamam. Yani, gerçekten bir şey anlamıyorum. Çok muhtemel olduğunu düşündüm. Ama sorunu hiç açıklamamışsın, üzgünüm. T, bir sınıfın temsilidir. Neden T kullandığım yerde T uzanıyor, başka bir yerde T uygulayacağım?
Gangnus

T verdiğiniz örnekteki @Gangnus, mutlaka bir sınıf olmayan tip parametresini ifade eder - Joachim'in size ne söylediğini görün . Bunun için uygulamalara izin vermek , bahsettiğim aynı karmaşaya yol açacak
gnat

Evet, zaten yorumunu gördüm. Yanıt verildiğinde cevap olarak işaretlenir. İkinize de teşekkür edene ve +1.
Gangnus

-1

Bir arayüz anlamaya çalışırken bir sonraki adım olarak arayüz odaklı programlama anlamak gerekir . Arayüzün gerçek kullanımının ne olduğunu söyler. Bir Java (veya başka bir dil) programında hangi rolü oynar.


2
Cevabınız OP'nin endişelerini nasıl ele alıyor? Daha açık olması için lütfen yanıtınızı düzenleyin .
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.