2011-10-12 8 views
11

Na przykład (i to jest bardzo uproszczone), załóżmy, że mam klasę dla każdej karty w talii kart ... np. klasa KingOfSpaces, klasa QueenOfSpades, klasa JackOfDiamonds itd. Wszystkie z nich mają rozszerzenie Card. Może być wiele wystąpień KingOfSpaces.W języku Java, jak mogę sprawdzić, czy kolekcja zawiera wystąpienie określonej klasy?

I mam ArrayList<Card>, z 5 obiektów w nim. Jak mogę sprawdzić, czy ta ArrayList zawiera co najmniej jedną AceOfDiamonds?

Odpowiedz

10

Zacznijmy od wskazania, że ​​używanie klas do tego rodzaju różnicowania jest prawie na pewno złą rzeczą. Powiedziałbym, że prawdopodobnie trzeba uczynić "Kartę" nieco bardziej inteligentną (tj. Posiadającą metodę getSuit() i getOrdinal()).

Ale jeśli nalegasz na zrobienie tego w ten sposób, wykonaj iterację listy tablic (możesz to zrobić w Google - to całkiem podstawowa rzecz) i porównaj każdy wpis na liście za pomocą operatora instanceof.

Oznaczyłeś to pytanie jako mające związek z "odbiciem", co nie wydaje się właściwe. Jesteś pewien, że nie chciałeś oznaczyć go "pracą domową"?

OK - co do cholery, oto kod:

List<Card> hand = ...; 
for(Card card : hand){ 
    if (card instanceof AceOfDiamonds) return true; 
} 

ale nie należy skonfigurować hierarchię klas tak - to straszne projekt.

+0

Jestem pewien, że to nie jest praca domowa ... Skończyłem mój stopień 5 lat temu :) Sądzę, że tego właśnie szukałem. Pomyślałem, że może być coś bardziej zwięzłego jak Arrays.containsInstanceOf (hand, AceOfDiamonds.class), ale przypuszczam, że nie. Im bardziej dogłębnie rozumiem, robię to w ten sposób, ponieważ karty, zamiast być jak karty do gry, są bardziej podobne do kart Magic: The Gathering, w których każda karta ma specjalną zdolność, która modyfikuje "stół" w niektórych droga. I podobnie jak Magic, nowe karty mogą wymagać późniejszego dodania. –

4

Spróbuj operatora instanceof:

if (myObject instanceof myType) { 
    System.out.println("myObject is an instance of myType!"); 
} 
1

można użyć następującego kodu:

private boolean findInstance(ArrayList items, String className) { 
    boolean tag = false; 
    for (int i = 0; i < items.size(); i++) { 
     if (items.get(i).getClass().getName().equals(className)) { 
      tag = true; 
      break; 
     } 
    } 
    return tag; 
} 

'className' zawiera nazwę pakietu, na przykład: 'java.lang.String'

+1

to ogólne podejście będzie działać (rodzaj), ale jest okropnie nieefektywne. Operator instanceof jest tam z jakiegoś powodu. Również twoja implementacja mogłaby zostać znacznie ulepszona przez zwracanie wartości true zamiast ustawiania tag = true. –

+0

Naprawdę będziesz chciał zachować ostrożność przy użyciu tej metody.Nie ma poczucia bezpieczeństwa typu, możesz mieć słabą wydajność, nie używając iteratorów, i nie jestem pewien, co stanie się z metodą getName() klasy. Myślę, że inne podejścia wymienione są nieco bardziej jasne. –

+0

@KevinDay gdy masz rację getclass samo jest śmieszne ustawienie tag jest lepszy niż powrót z wielu miejsc. – Shahzeb

4

@ Daniel Pereira odpowiada na pytanie. Chciałbym zaproponować, że to, czego naprawdę chcesz, to enum.

Przykłady:

enum Card { 
    KingOfSpades, 
    QueenOfSpades, 
    JackOfSpades, 
    // etc 
    AceOfDiamonds; 
} 

Card myCard = ...; 
if(myCard == Card.KingOfSpades) { 
    // stuff 
} 

Set<Card> cards = new EnumSet<Card>(Card.class); 
cards.add(...); 
if(cards.contains(myCard)) { 
    // stuff 
} 
+0

Byłbym drugi. Wyliczenie to odpowiednia struktura danych dla zestawów kart lub każdego uporządkowanego zestawu. –

0

Kontrola rodzaju obiektu zasadniczo różne zasady łamie obiektowego. Pytanie, które możesz chcieć odpowiedzieć, to to, co masz zamiar zrobić, gdy znajdziesz ten typ obiektu.

Czynność do wykonania będzie czasownikiem, który musi być modelowany dla każdego typu. Na przykład w grze w pasjansa po kliknięciu na kartę możesz umieścić ją na stosie po prawej, jeśli jest to as. Tak więc zdolność, czy karta może wylądować na stosie, zależy od samego obiektu, ponieważ zna jego tożsamość. Więc zasadniczo musisz zaimplementować metodę deal() do każdej karty i na podstawie tego, jaki jest obiekt, on wie, w jaki sposób transakcja() musi zostać zaimplementowana dla jej instancji. Robiąc to poza obiektem (i sprawdzając typ), w zasadzie złamałeś enkapsulację.

0
public static <E> boolean containsInstance(List<E> list, Class<? extends E> clazz) { 
    for (E e : list) { 

     try { 
      List<E> list2 = (List<E>) e; 
      for (E list21 : list2) { 
       System.out.println("<< ENCONTRO LISTA DENTRO DEL ARRAY DE OBJETOS >> "); 
       if (clazz.isInstance(list21)) { 
        return true; 
       } 
      } 
     } catch (Exception q) { 
      System.out.println("<< ENCONTRO OBJETO DENTRO DEL ARRAY DE OBJETOS >> "); 
      if (clazz.isInstance(e)) { 
       return true; 
      } 
      continue; 
     } 

    } 
    return false; 
} 
+2

Czy mógłbyś również wyjaśnić swoją odpowiedź, aby była pomocna dla przyszłych czytelników. – Prudhvi

Powiązane problemy