UNPKG

classtype

Version:

Это ООП библиотека для node.js, которая позволяет создавать полноценные классы на чистом JavaScript-е

538 lines (396 loc) 23.2 kB
# classtype: Это ООП библиотека для node.js **Classtype** - позволяет создавать полноценные классы на чистом JavaScript! ## Возможности * Полноценные области видимости (**public**, **protected**, **private**) * Наследование * Статические методы и свойства * Геттеры и сеттеры * Трейты * Конструктор ## Установка ``` npm install --save classtype ``` ## Подключение библиотеки ```js var CT = require('classtype'); ``` ## Построение классов на classtype Идея состоит в том, чтобы передавать в функцию `CT.extend()` в качестве аргументов вложенные объекты вида `{[область видимости]: {[имя свойства]: [значение по умолчанию]}}`, либо `{[область видимости]: {[имя метода]: function([параметры]) {[тело метода]}}}` #### Пример структуры ```js CT.extend( {[область видимости]: {[имя свойства]: [значение по умолчанию]}},// Свойство {[область видимости]: {[имя свойства]: [значение по умолчанию]}},// Свойство {[область видимости]: {[имя метода]: function([параметры]) {[тело метода]}}},// Метод {[область видимости]: {[имя метода]: function([параметры]) {[тело метода]}}}// Метод ) ``` #### Объявление класса ```js var [имя класса] = CT.extend([объявление свойств и методов]); ``` ```js var MyClass = CT.extend(/* свойства и методы перечисленные через запятую */); ``` #### Объявление наследника класса (наследование) ```js var [родитель] = CT.extend([объявление свойств и методов]); var [наследник] = [родитель].extend([объявление свойств и методов]); ``` ```js var MyClass = CT.extend(/* свойства и методы перечисленные через запятую */); var MyClass2 = MyClass.extend(/* свойства и методы перечисленные через запятую */); ``` ## Полноценные области видимости Область видимости свойства или метода может быть определена путем использования следующих ключевых слов в объявлении: public, protected или private. Доступ к свойствам и методам класса, объявленным как public (публичный), разрешен отовсюду. Модификатор protected (защищенный) разрешает доступ текущему и наследуемым классам. Модификатор private (приватный) ограничивает область видимости так, что только класс, где объявлен сам элемент, имеет к нему доступ. ### Пример #1 Объявление свойств класса Свойства класса должны быть определены через модификаторы **public**, **protected**, или **private**. ```js var [имя класса] = CT.extend( {[область видимости свойства]: {[имя свойства]: [значение по умолчанию]}} ); ``` #### Объявление свойств ```js var MyClass = CT.extend( {public: {test1: '123'}},// Публичное свойство {protected: {test2: '123'}},// Защищенное свойство {private: {test3: '123'}}// Приватное свойство ); ``` #### Доступ к свойствам ```js var MyClass = CT.extend( {public: {publicProperty: 'Публичный'}}, {protected: {protectedProperty: 'Защищенный'}}, {private: {privateProperty: 'Приватный'}}, {public: {printHello: function() { console.log(this.publicProperty); console.log(this.protectedProperty); console.log(this.privateProperty); }}} ); var obj = new MyClass(); console.log(obj.publicProperty); // 'Публичный' console.log(obj.protectedProperty); // undefined console.log(obj.privateProperty); // undefined obj.printHello(); /* Выводит: 'Публичный' 'Защищенный' 'Приватный' */ ``` ### Пример #2 Наследование свойств класса В данном примере создается класс **MyClass2**, который наследует свойства класса **MyClass** из предыдущего примера. Обратите внимание, что свойство ***privateProperty*** не наследуется. ```js var MyClass2 = MyClass.extend(); var obj2 = new MyClass2(); console.log(obj2.publicProperty); // 'Публичный' console.log(obj2.protectedProperty); // undefined console.log(obj2.privateProperty); // undefined obj2.printHello(); /* Выводит: 'Публичный' 'Защищенный' undefined <-- Свойство privateProperty не наследуется! */ ``` ### Пример #3 Объявление методов класса Методы класса должны быть определены через модификаторы **public**, **protected**, или **private**. ```js var [имя класса] = CT.extend( {[область видимости метода]: {[имя метода]: function([параметры]) {[тело метода]}}} ); ``` #### Объявление методов ```js var MyClass = CT.extend( {public: {method1: function(param) {/* тело метода */}}},// Публичный метод {protected: {method2: function(param) {/* тело метода */}}},// Защищенный метод {private: {method3: function(param) {/* тело метода */}}}// Приватный метод ); ``` #### Доступ к методам ```js var MyClass = CT.extend( {public: {myPublic: function() { console.log('Публичный метод'); }}}, {protected: {myProtected: function() { console.log('Защищенный метод'); }}}, {private: {myPrivate: function() { console.log('Приватный метод'); }}}, {public: {printHello: function() { this.myPublic(); this.myProtected(); this.myPrivate(); }}} ); var obj = new MyClass(); obj.myPublic(); // 'Публичный метод' obj.myProtected(); // TypeError: Object #<Object> has no method 'myProtected' obj.myPrivate(); // TypeError: Object #<Object> has no method 'myPrivate' obj.printHello(); /* Выводит: 'Публичный метод' 'Защищенный метод' 'Приватный метод' */ ``` ### Пример #4 Наследование методов класса В данном примере создается класс **MyClass2**, который наследует методы класса **MyClass** из предыдущего примера. Обратите внимание, что метод ***myPrivate*** не наследуется. ```js var MyClass2 = MyClass.extend(); var obj2 = new MyClass2(); obj2.myPublic(); // 'Публичный метод' obj2.myProtected(); // TypeError: Object #<Object> has no method 'myProtected' obj2.myPrivate(); // TypeError: Object #<Object> has no method 'myPrivate' obj2.printHello(); /* Выводит: 'Публичный метод' 'Защищенный метод' TypeError: Object #<Object> has no method 'myPrivate' */ ``` ## Наследование Наследование — механизм, позволяющий описать новый класс на основе уже существующего (родительского, базового) класса. Класс-потомок может добавить собственные методы и свойства, а также пользоваться родительскими методами и свойствами. Позволяет строить иерархии классов. В классе-наследнике могут быть переопределены любые свойства и методы любого родительского класса. ### Пример #1 Переопределение методов В данном примере класс **MyClass2** наследует метод ***method1*** и переопределяет метод ***method2*** класса **MyClass**, а также создает новый метод ***method3***. ```js var MyClass = CT.extend( {public: {method1: function() { console.log('Метод1'); }}}, {public: {method2: function() { console.log('Метод2'); }}} ); var MyClass2 = MyClass.extend( {public: {method2: function() { console.log('Переопределенный метод2'); }}}, {public: {method3: function() { console.log('Новый метод3'); }}} ); var obj2 = new MyClass2(); obj2.method1(); // 'Метод1' obj2.method2(); // 'Переопределенный метод2' obj2.method3(); // 'Новый метод3' ``` ## Ключевое слово this Для доступа к методам и свойствам текущего объекта используется ключевое слово **this**. ```js // Доступ к свойству текущего объекта function([параметры]) { this.[имя свойства]; } // Доступ к методу текущего объекта function([параметры]) { this.[имя метода]([параметры]); } ``` ```js // Доступ к свойствам var MyClass1 = CT.extend( {public: {test1: '123'}},// Публичное свойство {protected: {test2: '123'}},// Защищенное свойство {private: {test3: '123'}},// Приватное свойство {public: {method: function(param) { this.test1;// Доступ к публичному свойству this.test2;// Доступ к защищенному свойству this.test3;// Доступ к приватному свойству }}} ); // Доступ к методам var MyClass2 = CT.extend( {public: {method1: function(param) {/* тело метода */}}},// Публичный метод {protected: {method2: function(param) {/* тело метода */}}},// Защищенный метод {private: {method3: function(param) {/* тело метода */}}},// Приватный метод {public: {method4: function(param) { this.method1();// Доступ к публичному методу this.method2();// Доступ к защищенному методу this.method3();// Доступ к приватному методу }}} ); ``` ## Ключевое слово this.self Для доступа к статическим методам и свойствам текущего класса используется ключевое слово **this.self**. ```js // Доступ к статическому свойству текущего объекта function([параметры]) { this.self.[имя свойства]; } // Доступ к статическому методу текущего класса function([параметры]) { this.self.[имя метода]([параметры]); } ``` ```js // Доступ к свойствам var MyClass1 = CT.extend( {static: {public: {test1: '123'}}},// Публичное статическое свойство {static: {protected: {test2: '123'}}},// Защищенное статическое свойство {static: {private: {test3: '123'}}},// Приватное статическое свойство {public: {method: function(param) { this.self.test1;// Доступ к публичному статическому свойству this.self.test2;// Доступ к защищенному статическому свойству this.self.test3;// Доступ к приватному статическому свойству }}} ); // Доступ к методам var MyClass2 = CT.extend( {static: {public: {method1: function(param) {/* тело метода */}}}},// Публичный метод {static: {protected: {method2: function(param) {/* тело метода */}}}},// Защищенный метод {static: {private: {method3: function(param) {/* тело метода */}}}},// Приватный метод {public: {method: function(param) { this.self.method1();// Доступ к публичному статическому методу this.self.method2();// Доступ к защищенному статическому методу this.self.method3();// Доступ к приватному статическому методу }}} ); ``` Обратите внимание, что **this.self** и **this** это одно и тоже во всех статических методах! Мы рекомендуем использовать **this.self** дабы подчеркнуть, что обращение идет к статике. ```js var MyClass = CT.extend( {static: {public: {test: '123'}}},// Статическое свойство {static: {public: {method: function(param) {/* тело метода */}}}},// Статический метод {static: {public: {print: function(param) { // Доступ к статике внутри статики console.log(this.self.method1 === this.method1);// true console.log(this.self.test1 === this.test1);// true console.log(this.self === this);// true }}}} ); MyClass.print();/* Выводит: true true true */ ``` ## Статические методы и свойства Объявление свойств и методов класса статическими позволяет обращаться к ним без создания экземпляра класса. #### Объявление свойств ```js var [имя класса] = CT.extend( {static: {[область видимости]: {[имя свойства]: [значение по умолчанию]}}} ); ``` ```js var MyClass = CT.extend( {static: {public: {test1: '123'}}},// Публичное статическое свойство {static: {protected: {test2: '123'}}},// Защищенное статическое свойство {static: {private: {test3: '123'}}}// Приватное статическое свойство ); ``` #### Доступ к свойствам ```js var MyClass = CT.extend( {static: {public: {publicProperty: 'Публичный'}}}, {static: {protected: {protectedProperty: 'Защищенный'}}}, {static: {private: {privateProperty: 'Приватный'}}}, // Доступ через статический метод {static: {public: {staticHello: function() { // Можно через общепринятый this.self console.log('' + this.self.publicProperty); console.log(this.self.protectedProperty); console.log(this.self.privateProperty); // Но можно и напрямую через this console.log(this.publicProperty); console.log(this.protectedProperty); console.log(this.privateProperty); }}}}, // Доступ через динамический метод {public: {hello: function() { // Можно только через this.self console.log(this.self.publicProperty); console.log(this.self.protectedProperty); console.log(this.self.privateProperty); }}} ); console.log(MyClass.publicProperty); // 'Публичный' console.log(MyClass.protectedProperty); // undefined console.log(MyClass.privateProperty); // undefined MyClass.staticHello(); /* Выводит: 'Публичный' 'Защищенный' 'Приватный' 'Публичный' 'Защищенный' 'Приватный' */ var obj = new MyClass(); obj.hello(); /* Выводит: 'Публичный' 'Защищенный' 'Приватный' */ ``` #### Объявление методов ```js var [имя класса] = CT.extend( {static: {[область видимости]: {[имя метода]: function([параметры]) {[тело метода]}}}} ); ``` ```js var MyClass = CT.extend( // Публичный статический метод {static: {public: {method1: function(param) {/* тело метода */}}}}, // Защищенный статический метод {static: {protected: {method2: function(param) {/* тело метода */}}}}, // Приватный статический метод {static: {private: {method3: function(param) {/* тело метода */}}}} ); ``` ## Пример реализации класса на classtype ```js var User = CT.extend( // Статическое приватное свойство {static: {private: {count: 0}}},// Количество созданных юзеров // Статический публичный метод {static: {public: {getCount: function() { return this.self.count;// Возвращаем количество созданных юзеров }}}}, // Динамическое защищенное свойство {protected: {name: '123'}},// Имя юзера // Конструктор класса {private: {constructor: function(name) { this.self.count++;// Подсчитываем общее количество юзеров this.name = name;// Задаем имя юзеру }}}, // Динамический публичный метод {public: {getName: function() { return this.name;// Возвращаем имя юзера }}}, // Динамический публичный метод {public: {setName: function(name) { this.name = name;// Задаем новое имя юзеру }}} ); var user1 = new User('Саша'); var user2 = new User('Маша'); var user3 = new User('Даша'); console.log('Всего создано юзеров: ' + User.getCount());// 3 console.log('Имя первого юзера: ' + user1.getName());// 'Саша' user1.setName('Паша');// Задаем первому юзеру новое имя console.log('Новое имя первого юзера: ' + user1.getName());// 'Паша' console.log('Имя второго юзера: ' + user2.getName());// 'Маша' console.log('Имя третьего юзера: ' + user3.getName());// 'Даша' // Проверяем методы на прототип console.log(user1.getName === user2.getName);// true ``` ### Ссылки * http://closure-compiler.appspot.com/home * https://github.com/sole/tween.js/blob/master/README.md * http://habrahabr.ru/post/177465/ * (WebSocket на ActionScript) https://github.com/theturtle32/AS3WebSocket * (WebSocket на ActionScript) https://github.com/y8/websocket-as * (WebSocket на ActionScript) https://github.com/zcourts/higgs-fs * (child_process) http://millermedeiros.github.io/mdoc/examples/node_api/doc/child_processes.html#child_process.fork * (многопоточность в node) https://kuroikaze85.wordpress.com/2010/06/21/use-several-cores-nodejs/ * (хорошая wiki документация) https://github.com/twbs/bootstrap * https://github.com/bower/bower * (очень хорошая документация) https://github.com/caolan/async#reject ## Ключевые слова this и this.self В динамических методах для доступа к другим динамическим методам и свойствам текущего объекта нужно использовать ключевое слово **this**. В данной библиотеке доступ к свойствам и методам обеспечивает ключевое слово **this**. В данной библиотеке доступ к свойствам и методам внутри методов обеспечивается через ключевое слово **this**. Поведение **this** зависит от типа метода, в котором происходит вызов. В динамических методах **this** позволяет обратиться к другим динамическим методам и свойствам. Для доступа к статическим методам и свойствам в таких методах нужно использовать **this.self**. В статических методах **this** обеспечивает доступ к другим статическим методам и свойствам. Проще говоря, в статических методах и **this**, и **this.self** указывают на статические методы и свойства. В зависимости от того, в каком типе метода мы находимся, это слово работает по разному. В динамических методах оно позволяет обратиться к другим динамическим методам и свойствам. В статических методах ключевое слово **this** обеспечивает доступ к статическим методам и свойствам. Для доступа к методам и свойствам текущего объекта используется ключевое слово **this**. Для доступа к динамическим методам и свойствам текущего объекта используйте ключевое слово **this**.