Наследование компонентов

На странице приведена информация по наследованию от компонентов продукта «Форсайт. Аналитическая платформа» и расширению их возможностей.

Пространства имён

Все классы, глобальные функции и перечисления должны быть определены в пространстве имён PP или его подпространстве определенным образом. Например:

PP.initNamespace(PP.Ui = {}, "PP.Ui"); 

Второй параметр определяет имя ресурса, который должен загружаться  вместе с пространством имён.

Классы

PP.Class1 = function (settings){};
PP.initClass(PP.Class1, baseClasses, "PP.Class1", baseIntf);

baseClasses  - ссылка на базовый класс, либо массив, первый элемент которого базовый класс, а последующие - объекты примеси.

baseIntf  - массив интерфейсов, которые реализует данный класс.

Каждый класс должен наследоваться от базового класса PP.Object.

Конструктор класса принимает на вход первый параметр - settings. Это объект со значениями свойств для создаваемого объекта. Пример:

PP.Class1 = function (settings){
      this._ImageUrl = "";
      this._Caption = "text";
      PP.Class1.base.constructor.apply(this, arguments); //Вызов конструктора базового класса
};
var c = new PP.Class1({ImageUrl : "url", Caption : "someText"});

После того как конструктор сработал, мы получим объект с заполненными полями из settings.

Следует отметить, что до вызова конструктора базового класса описываются те поля, которым можно присвоить значения через settings, служебные поля описываются после вызова базового конструктора.

Свойства

Описание свойства класса состоит из следующих шагов:

Описание поля свойства в конструкторе класса, например, ImageUrl как указано в примере выше.

Имя поля следует именовать с префиксом «_» и с прописной буквы. Если поле класса имеет тип ( Boolean | Number | String ), то его начальное значение следует определять как ( false | 0 | "" ) соответственно. Описание геттера и сеттера свойства делается через определение в прототипе класса функций:

PP.Class1.prototype.setImageUrl = function (value){
      this._ImageUrl = value;
};
PP.Class1.prototype.getImageUrl = function ()
{
      return this._ImageUrl;
};

Если свойство только на чтение, то не нужно определять сеттер-функцию; если свойство только на запись, то соответственно не нужно определять геттер.

Если данные функции не несут в себе никакой логики, то для снижения объема кода, рекомендуется определять геттер/сеттер через вспомогательную функцию:

PP.Object.defineProps(PP.Class1, ["ImageUrl"], true);

Последний параметр определяет, нужно ли генерировать сеттер для данного свойства.

Если свойство имеет параметры, то описывать геттер и сеттер необходимо следующим образом:

PP.Class1.prototype.set<PropertyName> = function (value, param1, param2, param3)
{
      this._Property = value;
};
PP.Class1.prototype.get<PropertyName> = function (param1, param2, param3)
{
      return this._Property;
};

То есть в сеттере первым параметром всегда идёт присваиваемое свойству значение.

Методы

Методы класса следует определять через функцию в прототипе:

PP.Class1.prototype.start = function ()
{

...

};

Public методы именуются обычным образом. Protected/private методы определяются также в прототипе класса и именуются с префиксом «_».

События

События реализуются через класс PP.Delegate. Каждое событие компонента должно быть явно определено, например:

PP.Component = function(settings)
{   
      this._defineEvents(["Click", "MouseOut"]);  //Все события определяются до вызова конструктора базового класса
      PP.Component.base.constructor.apply(this, arguments);
}
var c = new PP.Component();
c.Click.add(<обработчик или другой делегат>, <Контекст работы обработчика, по умолчанию это объект c>);
c.Click.remove(<обработчик или идентификатор обработчика события>, <контекст вызова обработчика>);

Каждый обработчик события вызывается в некотором контексте с двумя параметрами:

Обработчики событий следует именовать с префиксом «on», а сами события без префикса «on». События следует именовать по стандарту http://msdn.microsoft.com/ru-ru/library/ms229012.aspx по правилу UpperCamelCase. В именах событий используйте глаголы или фразы на основе глаголов. Обозначайте прошлое и будущее в именах событий, используя прошедшее и будущее времена. Например, событие закрывания, генерируемое перед закрытием окна, будет называться «Closing», а то, которое генерируется после закрытия окна, будет называться «Closed». Для обозначения предыдущих или последующих событий не используйте префиксы и суффиксы «Before» и «After». В сигнатурах обработчиков событий используйте два параметра с именами «sender» и «args». Параметр sender должен хранить ссылку на объект-генератор события, а параметр args должен быть json объектом с параметрами события.

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

new PP.Component({
      Click: function () { alert(1) },
      MouseOut: PP.Delegate(function () { alert(2) }, window)
})

Статические члены класса

Статические члены класса определяются как поле в объекте конструктора класса:

PP.Class1.func = function()
{
};

Запрещается описывать классы/интерфейсы/перечисления внутри других классов.

Константы

Константы классов должны быть описаны в верхнем регистре, например:

PP.Class1.CONST = "Значение";

Перечисления

Перечисления должны описываться через следующую конструкцию:

(PP.ColorType = function ()
{
       var t = PP.ColorType;
       t.HSV = "HSV";
       t.RGB = "RGB";
       t.ARGB = "ARGB";
       t.PPBI = "PPBI";
       PP.initEnum(t, "PP.ColorType");
})();

Интерфейсы

Интерфейсы должны описываться следующим образом:

(PP.IDisposable = function ()
{
      PP.initInterface(PP.IDisposable, "PP.IDisposable", <base>);
      PP.IDisposable.Data = PP.ClassMembers.Property;
      PP.IDisposable.PropertyChanged = PP.ClassMembers.Event;
      PP.IDisposable.dispose = PP.ClassMembers.Method;
})();

Имена интерфейсов должны начинаться с «I».

<base> - ссылка на базовый интерфейс или массив  интерфейсов.

Примеси

Примеси описываются обычным js объектом с набором функций:

PP.Ui.Mixin = {
      func : function() {}
};

В примеси могут быть определены только функции.

Комментарии

Следует использовать комментарии только через двойной слеш //.

Исключительные ситуации

Генерацию ошибок необходимо делать через оператор:

throw PP.Exception("message", <context>)

Используя следующий набор ошибок:

PP.Exception, PP.ArgumentException, PP.ArgumentNullException, PP.OutOfRangeException.

Запрещается использовать оператор try catch для передачи управления в другой участок кода или для заглушки ошибок.

Следующая статья: Принципы кодирования