Java Generics Çoklu Sınıflarla Joker Karakter Oluşturma


385

Bir Class nesnesine sahip olmak istiyorum, ancak temsil ettiği her sınıfı A sınıfını genişletmeye ve B arabirimini uygulamaya zorlamak istiyorum.

Yapabilirim:

Class<? extends ClassA>

Veya:

Class<? extends InterfaceB>

ama ikisini de yapamam. Bunu yapmanın bir yolu var mı?

Yanıtlar:


613

Aslında, istediğinizi yapabilirsiniz . Birden fazla arabirim veya bir sınıf artı arabirim sağlamak istiyorsanız, joker karakterinizin şöyle görünmesini sağlamalısınız:

<T extends ClassA & InterfaceB>

Bkz Jenerik Eğitimi sun.com de, özellikle Sınırlı Tipi Parametreler sayfanın alt kısmında, bölüm. & InterfaceNameGereksinim duyduğunuz her bir arabirimi kullanarak, isterseniz birden fazla arabirimi listeleyebilirsiniz .

Bu keyfi olarak karmaşık olabilir. Göstermek için, Collections#max(iki satıra sarılmış olan) JavaDoc bildirisine bakın :

public static <T extends Object & Comparable<? super T>> T
                                           max(Collection<? extends T> coll)

neden bu kadar karmaşık? Java Generics SSS'de belirtildiği gibi: İkili uyumluluğu korumak için .

Bu, değişken bildirimi için işe yaramaz gibi görünüyor, ancak bir sınıfa genel bir sınır koyarken işe yarıyor. Böylece, istediğinizi yapmak için birkaç çembere atlamanız gerekebilir. Ama sen bunu yapabilirsin. Sınıfınıza genel bir sınır koyarak böyle bir şey yapabilirsiniz ve sonra:

class classB { }
interface interfaceC { }

public class MyClass<T extends classB & interfaceC> {
    Class<T> variable;
}

Bunun için variableistediğiniz kısıtlama vardır. Daha fazla bilgi ve örnek için Java 5.0'daki Generics'in 3. sayfasına bakın . İçinde, <T extends B & C>sınıf adının önce gelmesi ve arayüzlerin ardından gelmesi gerektiğini unutmayın . Ve elbette sadece tek bir sınıfı listeleyebilirsiniz.


94
Bu yardımcı olur. Sınıfın önce gelmesi gerektiğini belirtmek gerekir , '<T, InterfaceB ve ClassA'yı genişletir' 'diyemezsiniz.
EricS

5
T için bir sınıfı genişletmek veya bir arabirim uygulamak için aynı şeyi nasıl yaparsınız?
Ragunath Jawahar

1
@RagunathJawahar: Bu konuda çok açık uçlu olamazsınız. Bazı sınırlarınız olmalı ve bunlardan biri önceden nerede arayüzlere sahip olacağınız ve nerede sınıflara sahip olacağınızı ve mirasınızı nasıl kullanacağınızı önceden biliyor. Bir sınıf veya arabirim olacaksa, bir type parametresini bilmek zorundasınız.
Eddie

4
Cevabınızın ilk satırı "joker karakterinizin böyle görünmesini sağlayın" der. ?Bu ifadede hiç yok , bu yüzden gerçekten bir "joker" mi? Ben sormak çünkü türü parametresi gerçekten bir joker olduğunda tüm "aynı anda iki şeyi genişletme" kavramını almak için alamıyorum.
The111

1
Evet, bu gerçekten bir joker karakter değildir ve OP'nin bir joker karakterle istediği şeyi yapamazsınız. Sen olabilir değil sadece bir joker ile etkili, OP istediğini yapmak.
Eddie

17

Bunu "anonim" tür parametreleriyle (yani, kullanılan joker karakterler ?) yapamazsınız, ancak "adlandırılmış" tür parametreleriyle yapabilirsiniz. Type parametresini yöntem veya sınıf düzeyinde bildirmeniz yeterlidir.

import java.util.List;
interface A{}
interface B{}
public class Test<E extends B & A, T extends List<E>> {
    T t;
}

2
Joker karakterlere neden izin verilmiyor? yani bunun neden geçerli olmaması gerektiğini anlamıyorum: ArrayList <? ClassA ve InterfaceB> listesini genişletir; Ve sonra bir öğeyi listeden çıkardıysanız, onu ClassA türünde veya InterfaceB türünde bir değişkene atayabilirsiniz
Mark

Joker karakteri bir değişkenle değiştirmek harika bir tekniktir! Ama her zaman işe yaramıyor. Örneğin, Java ek açıklama değeri türlerinde ad türü değişkenlere izin vermezken, joker karakterlere izin verir.
17'de
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.