enum singleton, ссылка на интерфейс, экземпляр на имя строки
Спасибо за просмотр моего вопроса, на который я не смог найти ответ в моих поисках / книгах. Я изучаю Java, написав roguelike, но я думаю, что этот вопрос больше связан с Java, чем с игрой. Не стесняйтесь обучать меня, если я ошибаюсь.
У меня есть похожие классы, которые я хочу, чтобы у каждого были определенные способности. Способности - это enum singletons с набором стандартных имен методов, которым я бы передавал Actor - я хотел избежать реализации методов из интерфейса в каждом классе Actor, и мне просто очень понравилось предполагаемое использование этого подхода по мере продвижения вперед. Я родом из shell / perl и не могу сказать, не думаю ли я о ООП, или у меня что-то полезное, и у меня еще нет навыков, чтобы справиться с этим.
addAbility (String) в StdActor - то, где это наконец сломалось в этом эксперименте.
Вопрос в том, делаю ли я здесь что-то неправильно? Если нет, как я могу это реализовать?
интерфейс для манипулирования способностями:
public interface ActorAbility {
// doesn't work, but need something to enable
// instance retrieval for addAbility...
public ActorAbility getInstance();
public void act(Actor actor);
public boolean isTickable();
}
Санитарная обработка интерфейса:
public enum ActorMove implements ActorAbility {
INSTANCE;
private ActorMove() {
}
public ActorAbility getInstance() {
return INSTANCE;
}
public void act(Actor actor) {
log.debug("Move");
}
public boolean isTickable() {
return true;
}
}
продезинфицировать использование способности. метод проб и ошибок. addAbility(String) не работает, копировать / вставлять из SO и в других местах. это, вероятно, должно быть взорвано с орбиты.
public class StdActor implements Actor {
private HashSet<ActorAbility> abilities = new HashSet<>();
// this whole method is wrecked
public void addAbility(String ability) {
// Class<? extends ActorAbility> action; // in a maze of twisty passages...
ActorAbility actionInstance = null;
try {
// action = Class.forName("game3.Actors.Abilities." + ability);
actionInstance = ActorAbility.valueOf("game3.Actors.Abilities."
+ ability);
} catch (Exception e) {
e.printStackTrace();
}
this.abilities.add(actionInstance);
}
}
вариант использования:
public class StdCharClass extends StdActor {
public StdCharClass() {
// I like this because it's clean and easily
// changeable
addAbility("ActorMove");
}
}
будущее запланированное использование:
HashSet<ActorAbility> abilities = actor.getAbilities();
for (ActorAbility ability : abilities) {
if (ability.isTickable()) {
ability.act(actor);
}
}
Спасибо!
РЕДАКТИРОВАТЬ: Спасибо за такой быстрый комментарий, JB. Я попробовал то, что вы предложили, и он, кажется, делает то, что я надеялся. Похоже, я был только в сорняках и должен был быть отозван.
1 ответ
Новый класс:
public enum Ability {
MOVE(ActorMove.INSTANCE), FIGHT(ActorFight.INSTANCE);
private ActorAbility ability;
private Ability(ActorAbility abilityClass) {
this.ability = abilityClass;
}
public ActorAbility getAbility() {
return this.ability;
}
}
StdActor:
public class StdActor implements Actor {
private HashSet<Ability> abilities = new HashSet<>();
public void addAbility(Ability ability) {
this.abilities.add(ability);
}
подкласс:
public class StdCharClass extends StdActor {
public StdCharClass() {
addAbility(Ability.MOVE);
}
}
и, наконец, использование:
HashSet<Ability> abilities = bob.getAbilities();
for (Ability ability : abilities) {
ActorAbility abilityClass = ability.getAbility();
if (abilityClass.isTickable()) {
abilityClass.act(bob);
}
}
выход!
12:44:15.835 [main] DEBUG ActorMove - Move