2014-01-15 2 views
1

Я получаю сообщение об ошибке, я не понимаю, на этом коде (отмечены в комментариях):Ошибка с использованием массива Java производных классов

public class Symbol { 
    private String name; 
    public Symbol(String name) { this.name = name } 
    public String name() { return name; } 
} 

public class Terminal extends Symbol { 
    public Terminal(String name) { super(name); } 
} 

public class NonTerminal extends Symbol { 
    public NonTerminal(String name) { super(name); } 
} 

public class Rule { 
    private NonTerminal lhs; 
    private Class<? extends Symbol>[] rhs; 

    public Rule(NonTerminal lhs, Class<? extends Symbol>... rhs) { 
     this.lhs = lhs; 
     this.rhs = rhs; 
    } 

    public String toString() { 
     StringBuilder sb = new StringBuilder(); 
     sb.append(lhs.name()); 
     sb.append(" ->"); 
     for(int i = 0; i < rhs.length; i++) { 
      sb.append(' '); 
      sb.append(rhs[i].name()); <<<<< ERROR! 
      // Get this error: The method name() is undefined for the type Class<capture#1-of ? extends Symbol> 

      // Tried: sb.append(((Symbol)rhs[i]).name()); 
      // Got error: Cannot cast from Class<capture#1-of ? extends Symbol> to Symbol 

     } 
     sb.append(';'); 
     return sb.toString(); 
    } 
} 

Ошибка задается в редакторе Java в Eclipse, не время компиляции.

В словах: Я хочу иметь возможность получить список Символов, терминалов или NonTerminals, и иметь возможность использовать их в соответствии с их классом.
Мое понимание, до сих пор было то, что Class<? extends Symbol> будет делать для любого объекта типа Symbol или получен из Symbol.

Так что мои вопросы:

  1. Почему публичный метод name(), определенный в классе символов, не может быть вызван. На самом деле все элементы в списке являются символами или производными от Symbol?

  2. Каков правильный способ вызывать name() из элементов массива?

EDIT я исправил sligthly код так (с изменениями, требуемых принятым ответом) это рабочий пример. Изменения изменить каждое вхождение

Class<? extends Symbol> 

в

Symbol 

Тест я использовал, чтобы проверить ответ:

Terminal t1 = new Terminal("t1"); 
    Terminal t2 = new Terminal("t2"); 
    Terminal t3 = new Terminal("t3"); 

    NonTerminal exp = new NonTerminal("exp"); 
    NonTerminal nt1 = new NonTerminal("nt1"); 
    NonTerminal nt2 = new NonTerminal("nt2"); 
    NonTerminal nt3 = new NonTerminal("nt3"); 

    Rule r1 = new Rule(exp, t1, nt2, t3); 

    Log.v(TAG, "The rule is: " + r1.toString()); 

Файл журнала показывает:

01-15 10: 18: 11.335: V/MainActivity (1732): правило: exp -> t1 nt2 t3;

ответ

2

Class<? extends Symbol> класс отражения - он сохраняет определение класса это Symbol или один из его подклассов.

В вашем примере вы хотите хранить экземпляров из Symbol (или один из его подклассов). Просто определите массив как это:

public class Rule { 
    private NonTerminal lhs; 
    private Symbol[] rhs; 

    public Rule(NonTerminal lhs, Symbol... rhs) { 
     this.lhs = lhs; 
     this.rhs = rhs; 
    } 
} 
+0

Когда я делать то, что вы предложили, я получаю ту же ошибку, но Somwhere еще: 'this.rhs = шк;' (конструктор класса Rule) * Тип несоответствия: не может конвертировать Класс [] to Symbol [] * – ilomambo

+0

Также необходимо изменить ctor - я соответствующим образом внесла свой ответ. – Mureinik

+0

Это работает, см. Мой расширенный вопрос тела. Теперь я не понимаю, когда и как использовать 'Class ', но поскольку у меня есть решение, это останется теоретическим любопытством. – ilomambo

Смежные вопросы