Использование параметра супертипа определенных классов enum - PullRequest
0 голосов
/ 28 января 2011

У меня есть два класса синтаксического анализатора, и я хочу выдать исключение при сбое синтаксического анализа. Я хочу использовать то же исключение, ParserException, которое я хотел бы принять имя поля, которое вызвало сбой. Я думал использовать перечисления, но мне кажется, что тема не совсем понятна.

Как объявить fieldName в классе ParserException? enum, насколько я понимаю, должен быть супертипом для ParserA.Fields и ParserB.Fields, но не принимается.

Обратите внимание, что два перечислимых класса содержат различный набор перечислений , т. Е. Они не являются одним и тем же классом.

public class ParserA {

 public enum Fields {
  A_FIRST_FIELD
  A_SECOND_FIELD
 }


 public void parse() {
  ... 
 throw ParserException(Fields.A_FIRST_FIELD);  
 }

}

public class ParserB {

 public enum Fields {
  B_FIRST_FIELD
  B_SECOND_FIELD
 }

 public void parse() {
  ... 
  throw ParserException(Fields.B_FIRST_FIELD);  
 }

}



// Parser error
public class ParserException extends Exception {

 enum fieldName; // ????? what goes here?


 public ParserException(enum e) {
  this.fieldName = e;
 }

 public enum getFieldName() {  // ?????? how do I do something like this?
  return fieldName;
 }

}

Ответы [ 4 ]

1 голос
/ 28 января 2011

enum, насколько я понимаю, должен быть супертипом для ParserA.Fields и ParserB.Fields

Не enum , но Enum - это общий супертип (или, точнее, Enum<?>).Но, вероятно, вы не хотите его использовать, это слишком общее.Может быть лучше использовать что-то вроде

 // ParserExceptionKind is probably a better name
 public interface ParserEnum { 
      String name();
      // some useful methods go here
 }

 public class ParserA implements ParserEnum {
      public enum Fields {
           A_FIRST_FIELD
      }
 }

 public class ParserException extends Exception {
      private ParserEnum parserEnum;
      ...
 }

Однако, в большинстве случаев лучше создавать отдельные подклассы Exception.

1 голос
/ 28 января 2011

Ну, вы могли бы иметь ParserException для хранения Enum<?>, но это действительно не дает вам никакого реального преимущества по сравнению с простым использованием Object в качестве типа для поля в ParserException.

За исключением изменения дизайна того, что вы здесь делаете, я бы предпочел сделать интерфейс маркера с именем Field и иметь все ваши enum, представляющие поля, реализующие это ... затемParserException может использовать Field в качестве типа объекта, который он хранит.

public interface Field {
}

...

public enum Fields implements Field {
  A_FIRST_FIELD,
  A_SECOND_FIELD
}

...

public class ParserException extends Exception {
  private final Field field;

  public ParserException(Field field) {
    this.field = field;
  }

  public Field getField() {
    return field;
  }
}

По большей части, это что-то enum должно быть деталью реализации, о которой больше не нужно заботиться.

0 голосов
/ 28 января 2011

ParserA.Fields и ParserB.Fields не имеют общего суперкласса (за исключением необработанного типа Enum или Object, но я сомневаюсь, что это поможет вам здесь).

Поскольку перечисления не могут быть расширены, я не понимаю, как вы могли бы решить эту проблему с помощью перечислений.

Вы можете обойти эту проблему, изменив enum на class и позволив как ParserA.Field, так и ParserB.Field расширить ParserException.Field. Однако, чтобы получить те же преимущества, что и enums, вам нужно ограничить количество экземпляров. Есть несколько способов добиться этого, например, сделать конструктор защищенным и иметь ограниченное количество открытых статических членов этого типа.

0 голосов
/ 28 января 2011

Просто используйте Fields тип, как вы сделали бы с обычным классом.

Fields fieldName;

и аналогичные в других случаях.

Кстати, перечисления обычно называются в единственном числе (опять же, как и в случае с классами, перечисления не , что отличается).

1012 * редактировать *
Вы можете использовать Enum class (общий суперкласс для всех перечислений) или даже Object.

Но, честно говоря, я не вижу особого смысла в объявлении enum-класса с одним элементом. Вы могли бы просто использовать строковые константы: те же функции и меньше путаницы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...