2014-11-10 2 views
1

Я использую библиотеку, которая содержит абстрактный общий оформленной класс:Java - Общий список общих абстрактных классов

public abstract class Parsable<T> { 
    T parse(String s); 
} 

Наследуя этот класс позволяет пользователям создавать экземпляры типов из строк. Мне приходится анализировать списки объектов. Например, может существовать IntParser extends Parsable<Integer>, и я хочу реализовать IntListParser extends Parsable<List<Integer>>. Это можно сделать довольно просто:

public class IntListParser extends Parsable<List<Integer>> { 
    List<Integer> parse(String s) { 
    IntParser ip = new IntParser(); 
    String[] strings = s.split(","); 
    List<Integer> result; 
    for (String s : strings) { 
     result.add(ip.parse(s)); 
    } 
    return result; 
    } 
} 

Это может быть сделано успешно для каждого типа синтаксического анализатора. В этом примере нет ничего особенного в Integer. После написания нескольких из этих одинаковых классов я решил, что пришло время создать родовое, чтобы сделать это:

public class GenericListParser<TParser extends Parsable<T>> extends Parsable<List<T>> { 
    List<T> parse(String s) { 
    TParser tp = new TParser(); 
    String[] strings = s.split(","); 
    List<T> result; 
    for (String s : strings) { 
     result.add(tp.parse(s)); 
    } 
    return result; 
    } 
} 

К сожалению, это не работает, потому что команда new TParser() не компилируется. Есть ли способ обойти это или я вынужден создать новую копию этого кода для каждого типа Parser?

Решения, которые я пытался это не сработало, являются:

  • Создание синтаксического анализа статической. Это предотвратит создание экземпляров Parsables, но это не сработает, потому что вы не можете создавать абстрактные статические функции.
  • Идет GenericListParser<TParser extends Parsable<T>> Продолжить Parsable<T> вместо Parsable<List<T>>. Это позволит его функции parse вызывать функцию разбора Parsable<T>, потому что это ее собственный супер. Это не работает, потому что возвращаемый тип анализа равен T, и вы не можете отличить List<T> в T.

ответ

4

Вместо того, чтобы пытаться создать парсер для чего-то неизвестного, принять его в качестве параметра:

public class GenericListParser<TParser extends Parsable<T>> extends Parsable<List<T>> { 
    private TParser tp = null; 
    public GenericListParser(TParser parser) { 
     this.tp = parser; 
    } 
    List<T> parse(String s) { 
    String[] strings = s.split(","); 
    List<T> result; 
    for (String s : strings) { 
     result.add(tp.parse(s)); 
    } 
    return result; 
    } 
} 
2

Я думаю, что ваш подход не правильный путь, и что вы должны удалить все классы список синтаксического анализа и заменить их, и новый «общий» класс, с одной типизированной статическим методом полезности:

public ststic <T> List<T> parseList(String s, Parsable<T> p) { 
    List<T> result = new ArrayList<>(); 
    for (String s : s.split(",")) 
     result.add(p.parse(s)); 
    return result; 
} 

Теперь вы можете назвать это так:

List<Integer> ints = parseList("1,2,3", new IntParser()); 

Если вам нужны отдельные классы для каждого списка синтаксического анализа, а затем:

public abstract class ListParser<T> extends Parsable<List<T>> { 
    private final Parsable<T> Parsable; 
    protected ListParser(Parsable<T> p) { 
     parsable = p; 
    } 
    public List<T> parse(String s) { 
     List<T> result = new ArrayList<>(); 
     for (String s : s.split(",")) 
      result.add(parsable.parse(s)); 
     return result; 
    } 
} 

Затем использовать:

public class IntListParser extends ListParser<Integer> { 
    public IntListParser() { 
     super(new IntParser()); 
    } 
} 
Смежные вопросы