Требование перечислений расширенных классов - PullRequest
0 голосов
/ 20 января 2011

Я хотел бы потребовать, чтобы классы, расширяющие мой абстрактный класс A, обеспечивали перечислимый тип.Мне не нужно ограничивать сам тип, я просто хочу убедиться, что они предоставляют какой-то перечислимый тип.Например, у меня есть абстрактный класс Animal, и я хочу убедиться, что у каждого Animal есть набор поведений.Мне не нужно ограничивать это поведение или создавать основной список каким-либо образом;Я просто хочу убедиться, что все Животные возвращают список символического поведения.

В идеале, я хотел бы сказать:

public abstract class Animal {
  public List<Enum> getBehaviors(); 
}

, но это не будет компилироваться чисто.1007 * Есть идеи?Было бы лучше подойти к этому через Generics?

Ответы [ 4 ]

2 голосов
/ 20 января 2011

Хорошо, я собираюсь немного расширить свой комментарий здесь.

Если вы хотите, чтобы ваш метод getBehaviors() возвращал список поведений для конкретного животного, заставляя сигнатуру метода объявить, чтоList<Enum<?>> возвращается ничего , чтобы помочь вам.Клиент, который получает ваш List<Enum<?>> от этого метода, не может сделать с ним ничего полезного (кто знает, что это такое?).Ограничение также ничего не делает для того, чтобы гарантировать, что тип объектов, содержащихся в списке поведения, на самом деле является «поведением», что бы это ни значило в контексте вашего приложения.Это могут быть дни недели, месяцы года или что угодно!

Я предполагаю, что у вас есть enum с DogBehavior (с константами, такими как BARK, BITE и т. Д.), И вы хотите убедиться, что в списке разрешено только такое поведение.Тот факт, что эти поведения собраны в enum s, является деталью реализации.Что вы должны сделать, это ввести общий интерфейс, который обозначает что-то как Behavior.Если нет конкретных методов, связанных с Behavior, это может быть просто интерфейс маркера (который не определяет методы).В противном случае вы можете захотеть, чтобы он имел несколько методов, таких как:

public interface Behavior {
  public String getName();
  public void doBehavior();
  // etc.
}

Затем у вас может быть несколько enum с, которые реализуют этот интерфейс:

public enum DogBehavior implements Behavior {
  BARK("Bark") {
    public void doBehavior() {
      // bark
    }
  },
  // etc.

  private final String name;

  DogBehavior(String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }
}

Затем 'Animal'может выглядеть так:

public abstract class Animal {
  public abstract List<Behavior> getBehaviors(); 
}

Что имеет для меня больше смысла.

2 голосов
/ 20 января 2011

Я немного запутался - если вы хотите, чтобы все Animal s экспортировали набор поведений, то в идеале ваша цель - написать что-то вроде этого:

Animal a = /* .. create some subtype of Animal .. */
List</* ?? */> behaviors = a.getBehaviors();

Проблема здесь в том, что если вы хотите, чтобы каждый Animal создал свой собственный перечисляемый тип для поведения, у вас не будет единого способа говорить об этих поведениях, если вы явно не укажете какой-либо тип, который их представляет.Другими словами, вы не можете заполнить /* ?? */ выше, если только в интерфейсе Animal не указан тип, с которым должны быть связаны все поведения Animal.

Один из вариантов - определитьКласс, подобный этому:

public final class Behavior {
    private final String name;

    public Behavior(String name) {
        this.name = name;
    }
    public String getBehaviorName() {
        return name;
    }
    /* ... etc. ... */
}

Тогда вы можете иметь каждый Animal тип, определяющий getBehaviors(), чтобы он возвращал список Behavior объектов.Это дает вам безопасную для типов среду для обсуждения поведения и, возможно, возможность добавлять более сложные действия для каждого поведения.

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

2 вещи, которые я вижу неправильно.

Сначала необходимо пометить этот метод как абстрактный.Вы не предоставили реализацию.

Во-вторых, Enum должен быть параметризован, если вы не хотите предупреждение.Enum<?> должно быть достаточно, если вам не нужно дополнительно ограничивать Enum.

Однако, как отметили другие, это, вероятно, НЕ то, что вы хотите.Перечень «поведений» бесполезен для вас.Они не имеют никакой функциональности, однажды возвращенной из getBehaviors ().Вы могли бы пройтись по ним и перечислить их, но это ничего не стоит больше, чем List<String>.

Я бы подумал, что вам нужен List<Behavior>, где Behavior - это интерфейс, который делает что-то для вас.

РЕДАКТИРОВАТЬ: ColinD выше избили меня до удара в той же точке.

0 голосов
/ 11 февраля 2014
public abstract class Animal {
  public List<? extends Enum<?>> getBehaviors(); 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...