Предотвращение ошибок и их устранение можно сравнить с вакцинацией и лечением болезни, после того, как вы ей заразились. Конечно, лучше потерпеть укол, чем сражаться с заболеванием. Эта метафора, но она хорошо применима к реальности. Ошибки подобны болезням: когда вы думаете, что победили их, применять эту метафору к отладке опасно, так как ошибки в коде подобны болезни – только решить, что избавился от нее, как она вновь проявляется совершенно неожиданным образом.
Расставляйте скобки явно
Очень часто ошибки возникают из-за неправильной интерпретации приоритетов операций. Я и сам не раз полагал, что точно помню, какой приоритет у данного оператора, а потом оказывалось, что ошибся. Взгляните на следующий пример:
int a = 37, b = 26; int n = a % 3 + b / 7 ^ 8
Если у вас хорошая память и вы можете без тени сомнения сказать, чему равно значение выражения, то вы – счастливчик! Для остальных это весьма рискованная строка кода, потому что она может давать множество результатов в зависимости от порядка выполнения операторов. На самом деле она возвращает единственное значение, которое вычисляется в соответствии с правилами языка программирования Java. Программисты легко могут перепутать порядок выполнения операторов, который приведет к ошибке вычислений. Каково же решение? Выход из этой ситуации – использовать скобки, даже если в этом нет необходимости, таким образом вы сможете контролировать порядок выполнения действий. Ниже приведен тот же самый код, но уточненный скобками:
int a = 37, b = 26;
int n = ((a % 3) + (b / 7)) ^ 8;
Скрытые переменные классаДругая ошибка, которая свойственна объектно-ориентированному программированию игр – это сокрытые переменные класса. Сокрытые переменные могут «потеряться», если в производном классе есть новая одноименная переменная. Взгляните на код, приведенный в листинге 16.1. Он реализует два класса Weapon и Bazooka.
Листинг 16.1. Классы Weapon и Bazookaclass Weapon {
int power;
int numShots;
public Weapon() {
power = 5;
numShots = 10;
}
public void fire() {
numShots–; //Переменная numShots в классе Weapon определена
}
}
class Bazooka : extends Weapon {
int numShots; //Переменная numShots скрывает переменную numShots родительского класса Weapon
public Bazooka() {
super();
}
public blastEm() {
power–;
numShots -= 2; //Переменная numShots класса Bazooka увеличивается, в то время как сокрытая переменная numShots класса Weapon остается неизменной
}
}