Чтение онлайн

ЖАНРЫ

JavaScript. Подробное руководство, 6-е издание
Шрифт:

return "(" + this, from + "..." + this, to + ")";

};

9.3. Классы в стиле Java

Если вам приходилось программировать на языке Java или других объектно-ориентированных языках со строгим контролем типов, вы, возможно, привыкли считать, что классы могут иметь четыре типа членов:

Поля экземпляра

Это свойства, или переменные экземпляра, хранящие информацию о конкретном объекте.

Методы экземпляров

Методы,

общие для всех экземпляров класса, которые вызываются относительно конкретного объекта.

Поля класса

Это свойства, или переменные, всего класса в целом, а не конкретного экземпляра.

Методы класса

Методы всего класса в целом, а не конкретного экземпляра.

Одна из особенностей языка JavaScript, отличающая его от языка Java, состоит в том, что функции в JavaScript являются значениями, и поэтому нет четкой границы между методами и полями. Если значением свойства является функция, это свойство определяется как метод. В противном случае это обычное свойство, или «поле». Но, несмотря на эти отличия, имеется возможность имитировать все четыре категории членов классов в языке JavaScript. Определение любого класса в языке JavaScript вовлекает три различных объекта (рис. 9.1), а свойства этих трех объектов действуют подобно различным категориям членов класса:

Объект-конструктор

Как уже было отмечено, функция-конструктор (объект) в языке JavaScript определяет имя класса. Свойства, добавляемые в этот объект конструктора, играют роль полей класса и методов класса (в зависимости от того, является ли значение свойства функцией или нет).

Объект-прототип

Свойства этого объекта наследуются всеми экземплярами класса, при этом свойства, значениями которых являются функции, играют роль методов экземпляра класса.

Объект экземпляра

Каждый экземпляр класса - это самостоятельный объект, а свойства, определяемые непосредственно в экземпляре, не являются общими для других экземпляров. Свойства экземпляра, которые не являются функциями, играют роль полей экземпляра класса.

Процесс определения класса в языке JavaScript можно свести к трем этапам. Во-первых, написать функцию-конструктор, которая будет определять свойства экземпляра в новом объекте. Во-вторых, определить методы экземпляров в объекте-прототипе конструктора. В-третьих, определить поля класса и свойства класса в самом конструкторе. Этот алгоритм можно упростить еще больше, определив простую функцию

defineClass.
(В ней используется функция
extend
из примера 6.2 с исправлениями из примера 8.3):

// Простая функция для определения простых классов

function defineClass(constructor, // Функция, определяющая свойства экземпляра

methods, // Методы экземпляров: копируются в прототип

statics) // Свойства класса: копируются в конструктор

{

if (methods) extend(constructor.prototype, methods);

if (statics) extend(constructor, statics);

return constructor;

}

//
Простейший вариант нашего класса Range

var SimpleRange =

defineClass(function(f,t) { this.f = f; this.t = t; },

{

includes: function(x) { return this.f<=x && x <= this.t;},

toString: function { return this.f + "..." + this.t; }

},

{ upto: function(t) { return new SimpleRange(0, t); } });

В примере 9.3 приводится более длинное определение класса. В нем создается класс, представляющий комплексные числа, и демонстрируется, как имитировать члены класса в стиле Java. Здесь все делается «вручную» - без использования функции

defineClass,
представленной выше.

Пример 9.3. Complexes: Класс комплексных чисел

/*

* Complex.js:

* В этом файле определяется класс Complex, представляющий комплексные числа.

* Напомню, что комплексные числа представляют собой сумму вещественной и мнимой части,

* где множитель і в мнимой части - это квадратный корень из -1.

*/

/*

* Функция-конструктор определяет поля экземпляра r и і

* в каждом создаваемом экземпляре.

* Эти поля хранят значения вещественной и мнимой частей комплексного числа:

* они хранят информацию, уникальную для каждого объекта.

*/

function Complex(real, imaginary) {

if (isNaN(real) || isNaN(imaginary)) // Убедиться, что аргументы - числа.

throw new ТуреЕггог; // Иначе возбудить исключение,

this.r = real; // Вещественная часть числа,

this.і = imaginary; // Мнимая часть числа.

}

/*

* Методы экземпляров класса определяются как свойства-функции объекта-прототипа.

* Методы, определяемые ниже, наследуются всеми экземплярами и обеспечивают общность

* поведения класса. Обратите внимание, что методы экземпляров в JavaScript

* должны использовать ключевое слово this для доступа к полям экземпляра.

Поделиться с друзьями: