| Беларусь, рогачёв |
Классы
Методы и свойства в прототипе
В этом подпараграфе мы переработаем наш код с тем, чтобы все нужное для нашего класса было сразу помещено в прототип.
Добавляем методы в прототип
Итак, открываем новый Флэш-файл и пишем там вот что:
// Конструктор
_global.lift = function (minFloor, maxFloor){
// Проверяем, не перепутал ли пользователь максимальный
// и минимальный этажи
if (minFloor < maxFloor){
this.minFloor = Math.round(minFloor);
this.maxFloor = Math.round(maxFloor);
}
else{ // Если перепутал, корректируем
this.minFloor = Math.round(maxFloor);
this.maxFloor = Math.round(minFloor);
}
// Устанавливаем лифт на 1 этаж (но если лифт туда не должен
// ездить, корректируем начальный этаж в нужную сторону).
this.currentFloor = Math.min(Math.max(1, this.minFloor), this.maxFloor);
this.doorsAreOpen = true;
}
// Функции - те же, что и раньше, но размещаем их в прототипе
_global.lift.prototype.goto = function(where){
trace("-----------");
// Oкругляем и ограничиваем этаж назначения
this.floorToGo = Math.min(Math.max(Math.round(where),
this.minFloor), this.maxFloor);
if (this.floorToGo != this.currentFloor) this.go();//Поехали!
else trace("Ничего не делаем." );
trace("-----------");
}
_global.lift.prototype.setDoorsOpen = function(open){
if (this.doorsAreOpen != open){
trace(open ? "Открываем двери." : "Закрываем двери.")
}
this.doorsAreOpen = open;
}
_global.lift.prototype.go = function(){
this.setDoorsOpen(false);
var distance = this.floorToGo - this.currentFloor;
var signOfDistance = (distance >= 0 ? 1 : -1);
for( // Это работает независимо от того, едем вверх или вниз
var i = this.currentFloor;
signOfDistance*i <= signOfDistance*this.floorToGo;
i += signOfDistance
){
trace("Этаж " + i);
this.currentFloor = i;
}
this.setDoorsOpen(true);
}
// Создаем 2 объекта
l1 = new lift(2, 5);
l2 = new lift(0, 3);
// Тестируем
trace("l1:");
l1.goto(4);
trace("l2:")
l2.goto(4);На выходе получаем:
l1: ----------- Закрываем двери. Этаж 2 Этаж 3 Этаж 4 Открываем двери. ----------- l2: ----------- Закрываем двери. Этаж 1 Этаж 2 Этаж 3 Открываем двери. -----------
Теперь, как видно, мы можем писать не new _global.lift, а просто new lift, поскольку объект по имени lift мы не создавали, а сразу разместили все нужные методы в поле prototype функции- конструктора. Также видно, что переработка конструктора дала свои плоды: лифт номер 1 поехал на четвертый этаж со второго, а не с первого, поскольку ниже второго этажа он спускаться не может.
Нужно ли добавлять поля в прототип
Мы можем добавить в прототип не только методы, но и поля. Те значения, которые мы установим для этих полей в прототипе, будут автоматически скопированы во все экземпляры классов. (Точнее, так будет казаться на первый взгляд, до тех пор, пока мы не разберемся в механизме copy-on-write.) Таким способом имеет смысл устанавливать значения полей по умолчанию или же значения констант. Если же значение поля в любом случае устанавливается в конструкторе, то можно обойтись и без помещения поля в прототип. В случае нашего лифта мы могли бы поместить в прототип поле doorsAreOpen и присвоить ему там значение true. Это соответствовало бы тому факту, что лифты нашей конструкции после монтажа стоят с открытыми дверьми.