0

Ich stecke fest, herauszufinden, wie ich Generics verwenden kann, um zu überprüfen, ob das gegebene Objekt aus einer Oberklasse das gewünschte Objekt aus einer der Unterklassen einer Unterklasse dieser Oberklasse ist . Lassen Sie mich ein Beispiel geben:Generics und type safety: Überprüfen der dynamischen Bindung von Argumenten

Lassen Sie uns sagen, dass wir diese Hierarchie haben:

public interface Expression{ 
    public Object evaluate(); 
} 

public abstract class BooleanExpression implements Expression{ 
    public abstract Boolean evaluate(); 
} 

public abstract class PositionExpression implements Expression{ 
    public abstract Integer[] evaluate(); 
} 

public class Conjunction extends BooleanExpression{ 
    public Boolean evaluate() 
} 

public class BooleanTrue extends BooleanExpression{ 
    @Override 
    public Boolean evaluate(){ 
     return true; 
    } 
} 

Nun ist mein Punkt ist, dass das Programm nur in der Lage sein sollte, ein Objekt aus Conjunction, wenn und nur wenn die gegebenen Argumente zu konstruieren, in Der Konstruktor ist entweder eine BooleanExpression oder eine Unterklasse dieser Klasse.

Ich habe mit Generika wie dies versucht:

public class Conjunction<T extends BooleanExpression> extends BooleanExpression{ 
    public Conjuction(T left, T right){ 
     this.left = left; 
     this.right = right; 
    } 

    private T left, right; 

    @Override 
    public Boolean evaluate(){ 
     return (left.evaluate() && right.evaluate()) 
    } 

Wenn ich eine Instanz erstellt werden soll, ich habe den folgenden Code:

public Expression createConjunction(Expression left, Expression right){ 
    return new Conjunction<BooleanExpression>(left, right) 
} 

Aber leider nicht kompilieren! Ich möchte Generics verwenden, um zu überprüfen, ob left und right Instanzen von BooleanExpression sind, weil ein Conjunction nur zwischen zwei booleschen Werten sein kann (und nicht ein PositionExpression). left und right können jedoch unterschiedlich sein BooleanExpression, left könnte ein Conjunction sein, während right könnte ein BooleanTrue (als Beispiel) sein.

Also eine Zusammenfassung: Ich möchte in der Lage sein, eine Instanz von Conjunction zu erstellen, wenn beide gegebenen Argumente left und right eine Unterklasse von BooleanExpression sind. Das Erstellen einer Instanz von Conjuction mit einem Argument, das eine Unterklasse von PositionExpression ist, sollte vom Compiler nicht akzeptiert werden.

Ich möchte dies lösen, ohne die createConjunction Methode und mit generischen Klassen/Schnittstellen zu ändern. Irgendwelche Ideen?

+0

Sie müssen die Funktion 'createConjunction' definitiv ändern, da sie in ihrer aktuellen Form einfach ungültig ist. Alles, was Sie ändern sollten, ist, die Typen von "links" und "rechts" "Boolescher Ausdruck" anstelle von "Ausdruck" zu machen. – luk2302

+0

Der Compiler macht genau das, was er soll.Es kompiliert nicht, weil "links" und "rechts" Ausdrücke sind, aber Ihr "Conjection" -Konstruktor erfordert explizit, dass diese Unterklassen von 'BoolescherAusdruck' sind. – Casey

+0

@Casey Ich denke, es gibt keine Möglichkeit für den Compiler zu überprüfen, ob das zugrunde liegende Objekt von 'left' von der Unterklasse' BooleanExpression' ist, oder? (zB wenn ich diese Methode 'createConjunction' nenne, könnte das' left' Argument ein 'BooleanTrue' enthalten, welches eine Unterklasse von' BooleanExpression' ist) ( –

Antwort

1
public Expression createConjunction(Expression left, Expression right){ 
    return new Conjunction<BooleanExpression>(left, right) 
} 

in dem obigen Verfahren, die Sie anfordern 2 expression Objekte, sondern in dem conjuction Konstruktor wird es zwei Objekte anfordert, die Sie bekommen, den Compiler-Fehler Booleanexpressions das ist der Teil erstreckt.

können Sie Ihre createConjuction Methode ändern

public Expression createConjunction(BooleanExpression left, BooleanExpression right){ 
     return new Conjunction<BooleanExpression>(left, right) 
    } 

oder Sie können den generic Ausdruck in conjuction Klasse

Conjunction<T extends Expression> extends BooleanExpression{} 
0

ändern Wenn Sie die Signatur createConjunction Methode und don halten wollen‘ Wenn Sie auch die Conjunction-Klasse ändern möchten, können Sie wahrscheinlich den Typ der Argumente in der Methode createConjunction überprüfen und umsetzen.