Enyo 2. ООП

от автора

image

Первый топик постигла участь многих пятничных постов, но не беда!
Я не сдаюсь, а значит мы продолжаем…

В этом топике мы осветим следующие темы:

  • Классы. Определение, создание экземпляров, наследование.
  • Методы и поля классов, конструкторы и методы базового класса

Disclaimer

Хабражители, я не претендую на истину в последней инстанции.
Мои познания JS и Enyo в частности — довольно ограничены, а потому tutorial является неполным.
Я настоятельно рекомендую всем заинтересовавшимся ознакомиться с офф. документацией.
Ссылки доступны в первой части, в приложении к текущему топику и конечно на enyojs.com.

Исходные данные

Использовать будем все тот-же файл «index.html»:

<!DOCTYPE html> <html>   <head>     <meta charset=utf-8>     <title>Title</title>     <link rel="stylesheet" href="http://enyojs.com/enyo-2.2.0/enyo.css"><!--Стили Enyo 2.2.0-->     <script type="text/javascript" src="http://enyojs.com/enyo-2.2.0/enyo.js"></script><!--Сам Enyo 2.2.0-->   </head>   <body>    <script type="text/javascript">   </script>    </body> </html> 

Все примеры будут изменять код внутри тега <script type="text/javascript"></script>.

Классы. Определение, создание экземпляров, наследование.

Определение своих типов:

class ClassName {}

в Enyo конструкция будет иметь следующий вид

enyo.kind({name: 'ClassName'})

Создание экземпляра объекта не отличается оригинальностью:

var class_name = new ClassName()

Наследование немногим сложнее создания экземпляра:

class ClassNameA {} class ClassNameB extends ClassNameA {} 

в Enyo примет следующий вид:

enyo.kind({name: 'ClassNameA'}) enyo.kind({kind: 'ClassNameA', name: 'ClassNameB'}) 

Тут стоит оговориться: если в классических ООП языках экземпляр типа «ClassName» ссылается на участок памяти и не имеет каких либо выдающихся особенностей (в лучшем случае наследуется от класса Object), то в Enyo базовым классом по-умолчанию будет «enyo.Control» — блочный DOM-элемент с тегом div (суровое WEB наследие), т.е. для типа «ClassNameA» неявно базовым классом назначен «enyo.Control». Если это положение дел Вас не устраивает — наследуйте «enyo.Component».
Множественное наследование в стиле С++/Java/etc. обнаружить не удалось, везде где можно — утиная типизация, хотя может плохо искал.

Практикум

Возьмем наш «index.html» и впишем следующий код:

//Определяем наши классы enyo.kind({name: 'ClassNameA'}) enyo.kind({kind: 'ClassNameA', name: 'ClassNameB'})  //Создаем экземпляры объектов var cls_a = new ClassNameA() var cls_b = new ClassNameB()  //Выведем объекты в консоль console.dir(cls_a) console.dir(cls_b) 

Если проверить DOM то мы не обнаружим div элементов. Это связано с тем что ни у одного из классов не был вызван метод «renderInto()», тем не менее объекты, были созданы и инициализированы.

Методы и поля классов, конструкторы и методы базового класса

Классы — это хорошо, но зачем класс если не наполнять его функционалом? — Сейчас сделаем!
Имея псевдокод:

class ClassNameA {   object fieldName = "value" } 

превратим в Enyo код:

enyo.kind({name: 'ClassNameA', fieldName: 'value'})

Теперь мы можем создать экземпляр класса и проверить что поле класса доступно:

var cls_a = new ClassNameA() console.log(cls_a.fieldName)

Ок, но поля сами по себе мало что значат, где методы? — Да тут же, рядом!
Имея псевдокод:

class ClassNameA {   object method () {     return "value"   } } 

превратим в Enyo код:

enyo.kind({   name: 'ClassNameA',   method: function(){ return 'value' } })

Теперь мы можем создать экземпляр класса и проверить что метод класса доступен:

var cls_a = new ClassNameA() console.log(cls_a.method())

Ок, есть поля, есть методы… может еще и конструктор/деструктор есть? — Конечно! Конструкторов аж 2 штуки!!! Но, будем последовательны.
При создании любого Enyo объекта вызывается его метод constructor, если необходима инициализация — стоит его переопределить.
Выглядит это следующим образом:

 enyo.kind({   name: 'ClassNameC',   constructor: function() {     // Собственно конструктор     console.log('constructor')   } }) 

Для обращения к методу (в данном случае конструктору) базового класса в Enyo предусмотрена конструкция this.inherited(arguments). Стоит отметить что this.inherited(arguments) работает для всех методов которые вы планируете переопределять.
Как следствие код станет следующим:

 enyo.kind({   name: 'ClassNameC',   constructor: function() {     console.log('my init befor constructor')     this.inherited(arguments)     console.log('my init after constructor')   } }) 

Все вышеописанное справедливо для всех объектов Enyo создаваемых пользователем, но тут есть дополнение…
Тип «enyo.Component» — если вкратце, то этот зверь является одним из базовых классов для «enyo.Control» (того самого который по-умолчанию div).
Среди его полей и методов значатся:

  • name — поле отвечающее за типизацию/именование объектов
  • createComponent / createComponents — методы для динамического создания дочерних компонентов
  • destroyComponents — методы для динамического удаления дочерних компонентов
  • owner — поле-ссылка на родителя текущего компонента
  • id — думаю и так понятно
  • и много вкусных методов по работе с event-ами, но о них в следующих топиках

Как ни крути, а такой функционал достоин внимания. Так вот этот самый «enyo.Component» вводит еще 2 метода в жизненный цикл своих «детей»:

enyo.kind({   name: 'ClassNameD',    // Этот метод был рассмотрен ранее   constructor: function() {     this.inherited(arguments);   },    // Этот метод вызывается при createComponent / createComponents   create: function() {     this.inherited(arguments);   },    // Этот метод вызывается при destroyComponents   destroy: function() {     this.inherited(arguments);   } }); 

В чем соль? Да все очень просто!
Внутри «enyo.Component» и в частности «enyo.Control» может быть вложено множество элементов, а внутри них еще и т.д.
Как строить это дерево? Как связывать это дерево с DOM? Как пересчитывать размеры при добавлении / удалении элементов?
Как привязать / удалить event-ы? Чувствуете? Ага, свой маленький граф объектов с шашками и поэтессами!
Ради справедливости спешу сообщить что создание / удаление элементов и их фактическая отрисовка в DOM разнесены функционально.

Создание/Удаление дочерних элементов при создании нового экземпляра происходит по create/destroy. Доступ к вышестоящему узлу осуществляется по полю «owner», а к дочерним узлам по «this.$»
Офф. документация гласит: если ваш объект унаследован от «enyo.Component» или его потомков — используйте в качестве конструктора create т.к. он вызывается сразу после constructor, в противном случае — constructor.
Итог:

enyo.kind({   name: 'ClassNameD',    create: function() {     // this.$ - пуст     this.inherited(arguments)     // this.$ - содержит дочерние элементы, и их методы create уже завершены   },    destroy: function() {     // this.$ - содержит дочерние элементы     this.inherited(arguments);     // this.$ - пуст   } }); 

Ссылки

Наследование в Enyo. GitHub wiki Enyo
Object lifecycle Enyo. GitHub wiki Enyo
enyo.Component. Enyo API
enyo.Control. Enyo API

Как подан материал?

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

Никто ещё не голосовал. Воздержавшихся нет.

ссылка на оригинал статьи http://habrahabr.ru/post/204598/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *