2017-12-19 291 views
7

Ben bir arayüz Bar çağrıda ve bir türüne parametreli bir jenerik sınıfı Fooolduğunu birBar:Java genel sınıfında, yapıcı düzeyinde ek genel kısıtlamalar ekleyin?

class Foo<B extends Bar> { } 

Benim sınıf bir Class ve Stream alan bir genel amaçlı Oluşturucu sahip:

class Foo<B extends Bar> { 
    B[] bs; 
    Foo(Class<B> clazz, Stream<B> stream) { // General ctor 
     bs = someFunctionOf(clazz, stream); 
    } 
} 

Her ikisi de gerçek yöntem parametresi gerektiren özel bir kurucu eklemeye çalışıyorum

class Foo<B extends Bar> { 
    B[] bs; 
    Foo(Class<B> clazz, Stream<B> stream) { // General ctor 
     bs = someFunctionOf(clazz, stream); 
    } 
    // FIX THIS ----+ 
    //    | 
    //    ˅ 
    Foo(Class<Something> clazz) { // Special ctor 
     // Can we make this work so Something is a Bar and an enum 
     // and we can call the other constructor like this? 
     this(clazz, Arrays.stream(clazz.getEnumConstants()); 
    } 
} 
+0

belki ('clazz.getEnumConstants ifade ediyor)'? 'Class' class' getEnumeratedValues ​​() 'yöntemine sahip değildir. –

+0

neden sadece 2 tane daha özel kurucu değil? –

+0

@JohnBollinger - Evet - Sorunun genellenmesi için yöntem adımı batırdım. Sabitleme :) – 0xbe5077ed

cevap

6

anlamda, jenerik kurucular yazabilir. Son zamanlarda a question about them, and how they might be useful vardı.

class Foo<B extends Bar> { 
    B[] bs; 
    Foo(Class<B> clazz, Stream<B> stream) { // General ctor 
     bs = someFunctionOf(clazz, stream); 
    } 

    private B[] someFunctionOf(Class<B> clazz, Stream<B> stream) { 
     return null; 
    } 

    <T extends SomeClass & Bar> Foo(Class<T> clazz) { 
     // ... 
    } 
} 

Ama olmak istediğiniz yere oldukça seni almaz: Bu şekilde, her iki bazı özel diğer sınıfını genişleten ve arayüz Bar uygulayan bir sınıfı temsil eden bir argüman olarak bir Class alan yapıcıya sağlayabilir Çünkü kurucunun tür argümanının T sınırlarının açık tip olması gerekir. Sınıfın type type parametresi B gibi değişkenler yazmaz ve T'u B'a bağlamanın bir yolu olmadan, özel jenerik kurucu genel kurucuya çağrı yapamaz.

Ama yerine özel bir yapıcı bir fabrika yöntemi ile yapabilirsiniz:

class Foo<B extends Bar> { 
    B[] bs; 
    Foo(Class<B> clazz, Stream<B> stream) { // General ctor 
     bs = someFunctionOf(clazz, stream); 
    } 

    private B[] someFunctionOf(Class<B> clazz, Stream<B> stream) { 
     return null; 
    } 

    static <T extends Enum<T> & Bar> Foo<T> createEnumFoo(Class<T> clazz) { 
     return new Foo<>(clazz, Arrays.stream(clazz.getEnumConstants())); 
    } 
} 
+0

olarak reddedildi Ayrıntılı açıklama için teşekkürler. Ben jenerik yapıcılar ile başarmak için bir yol olduğunu umuyordum ama dediğiniz gibi yapıcının tip parametresi sınırlarını 'tip parametresine geri bağlama yolu yoktur. Biraz sinir bozucu! Ama sanırım alternatif, anlaşılmaz bir kullanım durumunu hafifletmek için sözdizimini karmaşıklaştırmaktır. – 0xbe5077ed

-4

Bu & operatörünü kullanarak mümkündür: <Something extends Bar & Enum<?>>

+1

Yığın akışında, bir şeyi kendi satırına koyarak ve sonra da girerek kod bloğu olarak işaretleyebilirsiniz. Kodunuz bunu yapmaz, html olarak ayrıştırılır ve geçersiz html – Ferrybig

5

sanmıyorumBir Barve bir enum sınıf böyle ben özel yapıcı benim genel amaçlı kurucusunu çağırmak olmasıdır yapıcı ile yapabilirsin. Ya alt sınıfı oluşturmak:

class EnumFoo<B extends Enum<B>&Bar> extends Foo<B> { 
    public EnumFoo(Class<B> clazz) { 
     super(clazz, Arrays.stream(clazz.getEnumConstants())); 
    } 
} 

veya fabrika yöntemini:

Genellikle
public static <T extends Enum<T>&Bar> Foo<T> of(Class<T> clazz) { 
    return new Foo<>(clazz, Arrays.stream(clazz.getEnumConstants())); 
}