Прежде всего, я понятия не имею, отражает ли заголовок мой вопрос. Я прошу прощения и прошу изменить его, если у вас есть идея получше.
Теперь у меня проблема в основном с дизайном. Я не уверен, что то, что я хочу, это хорошая практика, но это очень удобно.
У меня есть интерфейс с именем IMovement .
Два класса реализуют IMovement : VelocityMovement , SplineMovement .
У меня также есть класс под названием Sprite . Спрайт имеет IMovement .
Наконец, у меня есть два подкласса Sprite: Игрок и Враг .
Я ЗНАЮ , что Игрок будет ВСЕГДА имеют VelocityMovement и
Я ЗНАЮ , что Враг будет ВСЕГДА иметь SplineMovement .
Неправильно ли (по замыслу или из практики) иметь, кроме ссылки на суперклассы на IMovement, атрибут для VelocityMovement или SplineMovement от Player или Enemy соответственно?
Другими словами:
Interface IMovement {
public Vector2 getPosition(int time);
}
class VeloctiyMovement implements IMovement {
public Vector2 velocity;
public Vector2 getPosition(int time) { ... }
}
class SplineMovement implements IMovement {
public Spline spline;
public Vector2 getPosition(int time) { ... }
}
class Sprite {
IMovement movement;
}
class Player extends Sprite {
public VelocityMovement velocityMovement;
public Player() {
velocityMovement = new VelocityMovement();
movement = velocityMovement;
}
}
class Enemy extends Sprite {
public SplineMovement splineMovement;
public Enemy() {
splineMovement = new SplineMovement();
movement = splineMovement();
}
}
Причиной, по которой я хочу получить ссылку в подклассе, является удобство. В половине случаев мне нужно поле скоростей от игрока, а в половине раз мне все равно. Это происходит в игре, где метод вызывается примерно 100 раз в секунду.
Причина, по которой я указываю 100 раз, заключается в том, что я также обеспокоен, стоит ли кастовать дорого.
Пример, вместо:
// When I need the velocity
Vector2 velocity = ((VelocityMovement)player.movement).velocity;
...
// When I don't care
Vector2 position = player.movement.GetPosition(time);
...
Теперь я могу сделать это:
Vector2 velocity = player.VelocityMovement.velocity;
...
Vector2 position = player.movement.GetPosition(time);
...
Итак, мой вопрос: должен ли игрок иметь поле VelocityMovement, а у врага - SplineMovement? Или это плохой дизайн?
Мне бы хотелось, чтобы ваши мысли.
UPDATE
Теперь я вспомнил, почему я выбрал поле IMovement вместо того, чтобы Sprite реализовывал IMovement (как правильно подсказывает JacobM ).
Это потому, что в некоторых случаях у врага может быть SplineMovement, а в других - VelocityMovement.
Хотя я неправильно сказал «Я ЗНАЮ, что Враг ВСЕГДА будет иметь SplineMovement», я должен был сказать, что я знаю, что враг имеет VelocityMovement в местах, где я собираю всех врагов с VelocityMovements. Надеюсь, вы меня понимаете (иначе я чувствую себя идиотом).
Например:
List<Enemy> enemies = GetAllVelocityMovementEnemies();
Я делаю это потому, что где-то в игровой логике я хочу воздействовать только на группу врагов, у которых есть VelocityMovements.
Итак, хотя ответ JacobM совершенно верен как дизайн, это не для моего случая. В противном случае мне пришлось бы создать подкласс Enemy с помощью EnemyVelocityMovement, EnemySplineMovement и т. Д. И т. Д.
Итак, извините за недоразумение, я решил, что Ответ Брайана Агнью является лучшим для моего дизайна.
О, и да, опасения за кастинг - это действительно преждевременная оптимизация. ;)