2010-11-18 7 views
3

Entschuldigung für den Titel: -/Wie können nicht-generische Klassen in eine generische Hierarchie integriert werden?

Ich schrieb einen Parser für einen Taschenrechner. Es funktioniert, aber ich mag meine Token-Hierarchie nicht. Der Parser sollte den konkreten Zahlentyp nicht kennen, z. es sollte für Double, BigDecimal usw. konfigurierbar sein, damit ich eine generische Token-Schnittstelle

public interface Token<T> { } 

public class NumToken<T> { 
    private final value T; 
    ... 
} 

public class OperatorToken<T> { 
    ... 
} 

Nun meine Frage ist, wie „strukturelles“ Tokens zu behandeln, die die gleichen, unabhängig von der Anzahl Typ sind, beispielsweise Klammern und Trennzeichen. Der generische Parameter ist in diesem Fall nicht nur nutzlos, er verhindert auch, dass ich eine Enum für diesen Typ verwende. Ein Enum wäre jedoch sehr nützlich, z. Es kann in Switch-Anweisungen verwendet werden.

Im Moment habe ich „gelöst“, das Problem auf diese Weise:

public enum CharToken implements Token<Object> { 

    OPEN('('), 
    CLOSE(')'), 
    SEPARATOR(','), 
    EOL(';'); 

    private final char ch; 

    private CharToken(char ch) { 
     this.ch = ch; 
    } 
} 

Dies funktioniert, aber zwingt mich wie List<Token<? super T>> überall int den Parser Dinge zu schreiben, und davon ausgehen, dass alle anderen Arten tatsächlich Token<T> sind, wenn Ich habe gecastet. Ich verwende das Typsystem hier eindeutig gegen den Strich: Aus typentheoretischer Sicht stoße ich an die Wand, weil Java in Scala keinen "bottom" -Typ wie "Nothing" hat (was perfekt passt). Gibt es eine bessere Lösung?

[Klärung]

T ist die erwartete Anzahl meine Parser arbeiten geben sollte, nicht den „Inhalt“ des Token. Z.B. für OperatorToken<T> Ich habe eine Methode calc(T op1, T op1). Und ich möchte in der Lage sein, den gesamten Parser mit T zu parametrisieren, so dass alle von ihm verwendeten Token das gleiche T benötigen (naja, wenn Sie nicht wie ich mit schummeln), und CharToken implements Token<Character> wäre daher nicht sehr nützlich.

+0

sollte es nicht sein 'implementiert Token ' – Bozho

+0

Was macht 'T' in' Token'? – khachik

Antwort

1

Eine Lösung im JDK (in zB java.util.Collections.emptyList()) verwendet Löschung ausnutzt - die Parameter des Typs wirklich nicht existieren, wie Sie sich erinnern könnte - und Inferenz Parametertyp für Methoden:

@SuppressWarnings("unchecked") 
public enum CharToken implements Token { // Note: No type parameter specified! 

    OPEN('('), 
    CLOSE(')'), 
    SEPARATOR(','), 
    EOL(';'); 

    public static <T> Token<T> open(){ return OPEN; } 
    public static <T> Token<T> close(){ return CLOSE; } 
    public static <T> Token<T> separator(){ return SEPARATOR; } 
    public static <T> Token<T> eol(){ return EOL; } 

    private final char ch; 

    private CharToken(char ch) { 
     this.ch = ch; 
    } 
} 

// Usage: 
Token<BigDecimal> bdOpen = CharToken.open(); 
Token<Integer> intOpen = CharToken.open(); 

Nicht sehr hübsch anzuschauen, aber zumindest ist es einfach zu bedienen. (Und aus Gründen der Sauberkeit möchten Sie vielleicht die Enumeration in einer Klasse kapseln, die nur die generischen Methoden freilegt.)

+0

Danke. Ich habe es so gemacht, und es funktioniert ziemlich gut. Trotzdem fühlt es sich an wie Betrug ... – Landei

0

Es gibt einen Void Typ in Java, der für ähnliche Zwecke entwickelt wurde. IMO der Typ Parameter sollte jedoch eher Character sein, wie Bozho vorschlägt.

Verwandte Themen