2014-12-31 17 views
6

Bir yönteme bildirmediğim belirli bir izin verilen tür kümesiyle List<T>'u nasıl geçirebilirim?Listede kullanım için Java'daki türleri kısıtlayın

E.g. Tamsayı, Boole ve String için türlerini sınırla: Ben List<Object> kullanırsanız O listede her şeyi koyabilirsiniz

// Pseudo code 
public void method(List<Integer OR Boolean OR String> myList); 

: Ben listesi kullanırsanız

public void method(List<Object> myList); 

Ben Parent tüm örneklerini koyabilirsiniz ve Bu listeye alt sınıfları:

public void method(List<Parent> myList); 

Bu yeterli olurdu f Bu alt sınıfları bildiren bendim (AllowedTypeA extends Parent). Ama kullanmak istediğim sınıfların sahibi olmadığımda ne yapabilirim (IntegerParent'u genişletemiyorum)?

+0

Sen ekspres "veya" Java tip kısıtlamaları olamaz. Bu tür bir kısıtlamaya ihtiyaç duyacağınız hangi yöntemi uygulamaya çalıştığınızı anlatabilir misiniz? –

+1

Generics muhtemelen yanlış bir çözümdür. Onlar "jenerik", yani isim olması gerekiyordu. Yalnızca belirli türlerini destekleyebiliyorsanız (veya türe özgü bir mantığa sahipseniz), muhtemelen her bir belirli tür için aşırı yüklenmiş yöntemler kullanmalısınız. – mellamokb

+3

@mellamokb Bu durumda aşırı yüklenme işe yaramazsa da, 'List <...>' argümanlarının tümü 'List' e geçecektir, bu yüzden başka parametreler olmadığı sürece bir çakışma olacaktır (ya da daha sonra adı farklı olan, bu durumda aşırı yüklenme olmaz)). –

cevap

2

Kavramsal olarak, @ laune'nin çözümünü daha çok tercih ederim. Willy-nilly üzerinde bir sürü şeyi bir listeye atmak ve izin verilen Türü eklemeyi unutmak için yazım ve derleme hatalarını tercih ederim.

Bu pratik yapmak için fazladan bir şeyler yapmanız gerekse de, yine de yapılması mümkündür, yani nesne türünü kaldırırsanız, muhtemelen ilişkili tüm nesneleri de silmeniz gerekir. Bununla birlikte, düzgün çalışmayı sağlamak için diğer yöntemlerin addAll gibi geçersiz kılınması gerekir.

Bu yaklaşım, laune'nin olsa da daha esnek olmasını sağlar, çünkü istediğiniz zaman permittedTypes ekleyebilirsiniz. Durumunuz için, muhtemelen en iyisi değil, ama genel soru, bir çekim yaptığım için hala ilgi çekicidir. Belki de bazı listelerinizin Integers'i saklamasını istiyorsunuz, ancak başkalarını değil. addPermittedObject yöntemini kullanarak bunu yapabilirsiniz. Ve

public class SelectiveList extends ArrayList<Object> { 
    //the (types of) objects that we can store 
    private ArrayList<Object> permittedObjects = new ArrayList<Object>(); 

    // put an Object type into the list 
    public boolean addPermittedObject(Object o) { 
     for (Object type : permittedObjects) { 
      if (type.getClass() == o.getClass()) { 
       return false; // if we already have it, do not add it again 
      } 
     } 
     return permittedObjects.add(o); // else let's add it 
    } 

    // remove the Object type 
    public boolean removePermittedObject(Object o) { 
     for (Object type : permittedObjects) { 
      if (type.getClass() == o.getClass()) { 
       return permittedObjects.remove(type); 
      } 
     } 
     return false; 
    } 

    @Override 
    public boolean add(Object o) { 
     for (Object type : permittedObjects) { 
      if (type.getClass() == o.getClass()) { 
       return super.add(o); // go ahead and add the item since it 
             // matches our list 
      } 
     } 
     return false; 
    } 
} 

bunu test etmek için:

public static void main(String[] args) { 
    SelectiveList selectiveList = new SelectiveList(); 
    selectiveList.add("Potato"); 
    selectiveList.add(1); 
    selectiveList.add(true); 
    System.out.println(selectiveList.size()); // prints 0 
    // these objects need to be initialized, but their contents do not 
    // matter 
    selectiveList.addPermittedObject(new String()); 
    selectiveList.addPermittedObject(new Boolean(false)); 
    selectiveList.addPermittedObject(new Integer(1)); 
    selectiveList.add("Potato"); 
    selectiveList.add(1); 
    selectiveList.add(true); 
    System.out.println(selectiveList.size()); // prints 3 
} 
+0

Sık sık olduğu gibi, (belki daha katı fakat) tip güvenli bir yaklaşımın veya çok esnek (çalışma zamanı yapılandırılabilir!) Bir yaklaşımın tercih edilip edilmeyeceğine karar verilir. – laune

+0

Bazı nesnelere gereksiz bir şekilde yalan söyleyen ve yalnızca türünü yapılandırmak için temsilcilerin oluşturulmasını gerektiren nesnelerin yerine, sınıfların bir “Liste > permittedTypes” listesinde tutulması tercih edilir. – laune

7

yapılacak en iyi şey bir sınıf içine bu karma liste sarın ve yöntemler İzin verilmesini istediğiniz sadece ne eklemek sağlamaktır:,

class WrappedMix { 
    private List<Object> oddsAndEnds = ... 

    public void add(Integer el){ oddsAndEnds.add(el); } 
    public void add(Boolean el){ oddsAndEnds.add(el); } 
    public void add(String el){ oddsAndEnds.add(el); } 
} 

Veya uygun Burada üste (ve aşırı yüklenme) ile ArrayList uzatmak

Neden böyle bir Listeyi istediğini merak etmeme rağmen - işlenmesi uygun değildir.

+0

Neredeyse mükemmel, thx! Gerçi bu bir “Liste” değil. Ancak bu fikir geçerlidir: Bir 'List ' öğesini uygulayın ve belirtilen nesne 'addOut' (Tamsayı),' Boolean' veya 'String'' add() 'yönteminin içinde değilse' IllegalArgumentException 'yazın. –

+0

İsterseniz, 'List' öğesini genişleten bir özel sınıf oluşturun, daha sonra bir 'CustomList ' özelliğine sahip olabilirsiniz ve 'instanceOf' işlevini daha kolay bir şekilde kullanabilirsiniz. – mbomb007