2011-03-26 22 views
5

Yaklaşık 10+ sınıfım var ve her birinin bir LUMP_INDEX ve SIZE statik sabiti var. Bu sınıfların her birinde, dizinin boyutunun bu iki sabit kullanılarak hesaplandığı bir dizi istiyorum. Şu anda i çizgisinde bir şey dizisini oluşturmak için her sınıf için bir işlevi vardır:Bu java kod çoğaltmayı devre dışı bırakma

private Plane[] readPlanes() 
{ 
    int count = header.lumps[Plane.LUMP_INDEX].filelen/Plane.SIZE; 
    Plane[] planes = new Plane[count]; 
    for(int i = 0; i < count; i++) 
     planes[i] = new Plane(); 

    return planes; 
} 

private Node[] readNodes() 
{ 
    int count = header.lumps[Node.LUMP_INDEX].filelen/Node.SIZE; 
    Node[] nodes = new Node[count]; 
    for(int i = 0; i < count; i++) 
     nodes[i] = new Node(); 

    return nodes; 
} 

private Leaf[] readLeaves() 
{ 
    int count = header.lumps[Leaf.LUMP_INDEX].filelen/Leaf.SIZE; 
    Leaf[] leaves = new Leaf[count]; 
    for(int i = 0; i < count; i++) 
     leaves[i] = new Leaf(); 

    return leaves; 
} 

vb Orada bu fonksiyonların 10 ve yalnızca farklar şekilde, sınıf türüdür Görebiliyorsunuz, bir ton çoğaltma var.

Bu çoğaltmanın nasıl önleneceğine dair herhangi bir fikri olan var mı? Teşekkürler. (Önceden benzer bir soru sordum, ama sanırım bunu sorduğum gibi).

+0

Dönüş ifadeleri geçersiz yöntemlerde var mı? –

+0

Bu yöntemlerde "başlık" nesnesi nedir? –

+0

Neden bir ArrayList kullanmadınız? – bancer

cevap

1

Okey doke ... Emin olmak için bunu test ettim ve aradığınız şeyi yaptığına inanıyorum.

public interface MyInterface 
{ 
    public int getSize(); 
    public int getLumpIndex(); 
} 

Sınıflarınız o arabirimini uygulayan:

Sen bir arabirim ihtiyaç header sahip, bir örneği olduğunu sınıfında

public class Plane implements MyInterface 
{ 

    ... 
    public int getSize() 
    { 
     return SIZE; 
    } 

    public int getLumpIndex() 
    { 
     return LUMP_INDEX; 
    } 

} 

...

public <E extends MyInterface> E[] 
    getArray(Class<E> c, MyInterface foo) 
{ 
    int count = lumps[foo.getLumpIndex()].filelen/foo.getSize(); 
    E[] myArray = (E[]) Array.newInstance(c, count); 
    for(int i = 0; i < count; i++) 
     myArray[i] = c.newInstance(); 
    return myArray; 
} 

Bunu, düzlem sınıfınız olarak şöyle diyebilirsiniz:

Plane[] p = header.getArray(Plane.class, this); 

:) Birisi şuna bakıp ben çıkıp çıkmadığımı görebilir mi?

(DÜZENLEME: yapmamı şimdi test ettik - yaradı)

ek bir not, getArray() argüman olarak büyüklüğünü ve indeksini almak yaparak her sınıfta alıcılar yok edebileceğini:

public <E extends MyInterface> E[] 
    getArray(Class<E> c, int size, int index) 
{ 
    int count = lumps[index].filelen/size; 
    E[] myArray = (E[]) Array.newInstance(c, count); 
    for(int i = 0; i < count; i++) 
     myArray[i] = c.newInstance(); 
    return myArray; 
} 

Ve diyoruz: sınıflarınızla içeriden

Plane p[] = header.getArray(Plane.class, SIZE, LUMP_INDEX); 

. Arayüz, jenerik türünü sağlamak için boş hale gelir ve alıcı yöntemlerini tanımlamanız gerekmez.

YA (son düzenleme söz veriyorum ama bu size seçenek vermek yapar ve jenerik hakkında biraz açıklar)

Hendek arayüzü.

Şimdi
public <E> E[] 
    getArray(Class<E> c, int size, int index) 
{ 
    ... 

bunu arabirimini tanımlamak veya uygulamak gerekmez, sadece çağrı:

yöntem umursamıyor çünkü ne bu kaldırır bunu vermek ne tür bir nesnenin bazı aklı kontrol ediyor
Plane p[] = header.getArray(Plane.class, SIZE, LUMP_INDEX); 
+0

Teşekkürler, muhtemelen bunu yapmanın en iyi yolu olduğunu düşünüyorum (getArray işlevinin header içinde olması gerekmiyorsa). Ancak, denediğimde, c.newInstance() bir InstantiationException atar ve neden olduğu hakkında hiçbir fikrim yok, bu yüzden güldüm. – terryhau

+0

Hiçbir zaman sizin kurucularınızın nesneleriniz için ne gönderdiğini hiç göndermediniz. Bağımsız değişken yapıcınız yok mu? –

+0

Evet, bağımsız değişkenleri yok. Onun istisnayı neden attığını anladım. Teşekkürler – terryhau

3

Java generics kullanın. Bu şekilde, her kullandığınızda bir genel yöntem yazabilir ve bir tür parametresi belirtebilirsiniz.

+0

Özel void read (Sınıf clazz) gibi bir şeyden mi bahsediyorsunuz? 2 sabitine clazz parametresi üzerinden erişemiyorum. – terryhau

+2

Jeneriklerle yeni T [x] 'yapamayacağınızı unutmayın. Buralarda dolaşabilirsin, ama cevap o kadar basit değil. –

+0

@Brian Roach: o zaman ne kullanmak için bir ipucu? Genel bir kapsayıcı mı? – xtofl

0

Kullanım jenerik, ancak koleksiyonunda koymak örneklerini oluşturmak için fabrika nesnesi çeşit geçmeniz gerekir, örneğin:

public class MyClass { 

public <E> E[] getArray(IObjectFactory builder, int index, int size){ 
    ArrayList<E> arrayList = new ArrayList<E>(); 
    int count = header.lumps[index].filelen/size;//wasn'tsure where header was coming from... 
    for(int i = 0; i< count; i++){ 
     E newInstance = builder.getNewInstance(); 
     arrayList.add(newInstance); 
    } 
    return (E[]) arrayList.toArray(); 
    } 
}  

interface IObjectFactory { 
<E> E getNewInstance(); 
} 
2

Bala çözümü yakındır. Yine de jenerik türden sabitlere erişemezsiniz, bu yüzden bir getCount() (veya onu adlandırmak istediğiniz her şeyi) ve her bir alt türü uygun sabitlerle uygulayacağım.

interface LumpySize<L extends LumpySize> { 
    int getCount(); // subtypes return the appropriate header.lumps[Plane.LUMP_INDEX].filelen/Plane.SIZE; 

    T[] initializeArray(); 

    abstract <T extends LumpySize> static class Base implements LumpySize<T> { 
     protected T[] initializeArray(Class<T> cls) { 
      int count = getCount(); 
      T[] lumps = (T[]) Array.newInstance(cls, count); 
      for(int i = 0; i < count; i++) { 
       try { 
        lumps[i] = cls.newInstance(); 
       } catch (Exception e) { // obviously this isn't good practice. 
        throw new RuntimeException(e); 
       } 
      } 
      return lumps; 
     }  
    }    
} 

class Plane extends LumpySize.Base<Plane> { 
    public int getCount() { 
     return header.lumps[Plane.LUMP_INDEX].filelen/Plane.SIZE; // assuming header is available somewhere 
    } 
    public Plane[] initializeArray() { return initializeArray(Plane.class); } 
} 
+0

Kodu yanlış okudunuz. Bu, örneğin sınıf düzlemi LumpySize.Base 'dizinini uzattığınız soyut bir taban sınıfıdır. –

+0

Doh, üzgünüm - Yanlış okumuştum. Yorumumu siliyorum. –

+0

+1. Evet. Uygulamaya bağlı sabitleri jenerik kod haline getirmenin yolu budur. Bilmek çok yararlı. – extraneon