Беларусь, рогачёв |
Классы
Методы и свойства в прототипе
В этом подпараграфе мы переработаем наш код с тем, чтобы все нужное для нашего класса было сразу помещено в прототип.
Добавляем методы в прототип
Итак, открываем новый Флэш-файл и пишем там вот что:
// Конструктор _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. Это соответствовало бы тому факту, что лифты нашей конструкции после монтажа стоят с открытыми дверьми.