2016-04-12 4 views
0

Lasst uns sagen, dass wir die folgende Klassenhierarchie haben:Wie erzwingen, dass eine Sammlung von Objekten, Instanzen des gleichen Kindes Klasse

public abstract class Parent { 
    // body of parent 
} 

public class ChildA { 
    // body of child A 
} 

public class ChildB { 
    // body of child B 
} 

Und wir haben eine Sammlung von Objekten des Typs Parent und eine Art und Weise zu füttern, dass Sammlung:

List<Parent> list; 

public void add(Parent newParent) { 
    list.add(newParents); 
} 

Wenn wir Hinzufügen von Elementen zu dieser Liste zu starten, wie können wir sicherstellen, dass sie nur Instanzen derselben Klasse sind? Entweder Instanzen von ChildA oder Instanzen von ChildB, aber nicht beide.

+0

aufzufüllen Warum nicht zwei Listen haben: eine 'Liste childsA;' und 'Liste childsB; '? Oder mehr auf den Punkt: warum interessiert es Sie, welche konkrete Instanz es ist? – Tunaki

+0

Weil das ist nicht, wie mein System funktioniert;) Ich brauche eine Liste der Eltern, aber sobald instanziierte Objekte hinzugefügt werden, sind nur diejenigen der gleichen Unterklasse erlaubt. – dabadaba

+0

Kein sehr solides Design für Ihr System. Das dynamische Eingeben einer Sammlung funktioniert nicht wirklich. Sicher können Sie Hacks erstellen, wie das Ersetzen der Sammlung durch eine 'Collections.checkedCollection', nachdem Sie das erste Element eingefügt haben, aber es ist kein gutes Design. – Kayaman

Antwort

1

Was Sie fragen, macht keinen Sinn.

Wenn Ihre Liste nur Objekte einer bestimmten Klasse enthalten soll; Dann benutze die Generika, um es zu sagen.

Es hat keinen Sinn, dem Compiler zu sagen "Hier ist eine Liste von Früchten"; um dann zu fragen: "und wie mache ich diese Liste zu einer, die nur Äpfel, aber keine Bananen braucht" ?! Der Punkt ist, es zunächst als eine "Liste von Äpfeln" zu deklarieren; Dann kann der Compiler alle Prüfungen für Sie durchführen.

+0

Weil es nicht Apfel oder Bananen ist. Es sind nur Äpfel: nur entweder grüne Äpfel oder rote Äpfel. – dabadaba

+1

Nun, dann überlegen Sie, eine Art von Marker-Schnittstelle zum Beispiel einzuführen. Sie wissen, wenn Sie den Compiler verwenden möchten, um die Arbeit für Sie zu erledigen ... müssen Sie dem Compiler etwas geben, um dies tun zu können. – GhostCat

2

Sie etwas tun könnte, wie

public void add(Parent newParent, Class<? extends Parent> clazz) { 
    if(clazz.equals(list.get(0).getClass()) { 
     list.add(newParents); 
    } 
} 
+0

Das ist näher an dem, was ich verlange. Aber kalt ist es möglich, dieses zweite Argument loszuwerden? Ich möchte wirklich die 'add' Methode transparent halten. Aber es scheint, als wäre das der einzige Weg, oder? – dabadaba

1

Da die Art der Liste auf dem ersten Element abhängen würde ihm hinzugefügt, gibt es keine Möglichkeit, eine Kompilierung Kontrolle zu haben. Das einzige, was man tun könnte eine hässliche Laufzeitprüfung wäre:

class Foo { 
    List<Parent> list; 
    Class<? extends Parent> clazz = null; 

    public void add(Parent newParent) { 
     if (clazz == null) { 
      clazz = newParent.getClass(); 
     } 
     if (! clazz.isInstance(newParent)) { 
      throw new IllegalArgumentException("wrong type"); 
     } 
     list.add(newParent); 
    } 
} 

Aber ich glaube nicht, dass Sie eine solche Gräuel verwenden sollten. Sie sollten stattdessen Ihr Design überdenken.

+0

Dies könnte funktionieren. Ich interessiere mich jedoch mehr für Ihren letzten Vorschlag. Könntest du mir helfen, es dann neu zu gestalten? Dies ist die tatsächliche Hierarchie: https://gist.github.com/kpagcha/46b63a339d32131c0f1570dbe4d442a0 Und wir hätten eine "Liste ". – dabadaba

1

erstrecken sich nur Arraylist zum Beispiel wie folgt aus:

public class WhackyArrayList<E> extends ArrayList<E> { 
    /** 
    * 
    */ 
    private static final long serialVersionUID = 1L; 

    public boolean add(E e) { 
     if (this.size() > 0) { 
      Object firstElement = this.get(0); 
      if (e.getClass().equals(firstElement.getClass())) { 
       return super.add(e); 
      } else { 
       return false; 
      } 
     } 
     return super.add(e); 
    } 
} 

Dann benutzen Sie einfach die normale Funktion add es

Verwandte Themen