abstractstock v1.1.2
AbstractStock
Данный пакет реализует концепцию абстрактного полиморфного класса с виртуальными методами и свойствами. Полиморфиз - одна из концепций ООП. Виртуальные методы и свойства - т.е методы свойства которые определяются в момент выполнения. Данныц класс позволяет организовать код, опираясь только на общее поведение и возрощаемое значение вызываемых методов, и сигнатуры их параметров.
Обзор
- Установка
- Отличие от предыдущей версии
- Документация
- Использование
- Зачем
- Терминология
- Внутренние перменные
- AS_stock
- ASlist
- API
- initStock
- abstractProp
- getASlist
- getStock
- AbstractStock.prototype.validStock
- deleteAbstractProp
- deleteStock
Установка
Так пакет abstractstock является пакетом nodejs - то вам для установки понадобится менеджер пакетов, к примеру npm.
Для установки пакета в качестве зависимомти другого пакета.
npm install abstractstock
Что бы скачать git репозиторий пакета - вам так же понадобится git. Выполните в терминалн следующий код
git clone https://github.com/dimkl-dev/AbstractStock.git && cd ./AbstractStock && npm install
Отличие от предыдущей версии
Версии 1.1 появилась возможность контроля присвоения и возврата значений абстрактных свойств и накпителя, так же при их определение добавлен опцианальный параметр debug выводящий отладочную информациию. Более подропный спсиок изменений:
в функции abstractProp и initStock добавлены следующие опциональные параметры:
- **verrifF**(desc)<span id='verrifF'></span> - опциональный парметр определяющий, при определение <a href="#Абстрактное-свойство">**абстрактного свойства**</a> и <a href="#Накопитель">**накпителя**</a>, функцию обратного вызова, которая вызывается перед присвоение, и возвратом значения. Чтобы значения возвращались и записывались - функция обязана возвращать значение. При вызове - в функцию передаётся в виде параметра, объект **desc** представляющий собой дескриптор свойства, и который имеет следующие свойства: - **name** - **String**: имя свойства(<a href="#Абстрактное-свойство">**абстрактного свойства**</a> или <a href="#Накопитель">**накпителя**</a>,) - **val** - **any**: значение свойства - **context** - контекст <a href="#Абстрактное-свойство">**абстрактного свойства**</a> или <a href="#Накопитель">**накпителя**</a>(т.е сам <a href="#Абстрактный-накопитель">**абстрактный накопитель**</a>) - **stock** - **true** если свойство является <a href="#Накопитель">**накопителем**</a>. **false** - во всех остальных случаях. - **prop** - **true** если свойство является <a href="#Абстрактное-свойство">**абстрактным**</a>. **false** - во всех остальных случаях. - **get** - **true** если значение возврощается свойством. **false** - во всех остальных случаях. - **set** - **true** если значение записывается свойством. **false** - во всех остальных случаях. - **debug** - опциональный параметр функций <a href="#abstractProp">**abstractProp**</a> и <a href="#initStock">**initStock**</a>. Если **true** - то будет выводится дополнительная отладочная информация. Подробности смотри в описании функций ниже. - **[deleteAbstractProp](#deleteAbstractProp)**(abstractname) - удаляет [абстрактное свойство](#Абстрактное-свойство) - **[deleteStock](#deleteStock)**(pname) - удаляет [накопитель](#Накопитель)
Документация
Подробная документация представлена ниже. Так же доступна документация в формате JSDoc.
Для её просмотра можно использовать пакет JSDocLive
Для просмотра JSDoc документации у пакета установленного как зависимость - в каталоге пакета наберите команду
cd ./node_modules/poolcall/ && jsdoclive ./
Если вы скачали git-репозиторий пакета наберите
jsdoclive ./
Использование
Зачем
Очень хороший вопрос зачем. JavaScript очень гибкий язык, но попробуйте взять ссылку на метод объекта и вызвать его в другом объекте
example
порпробуем взять у объекта obj1 метод say и вызвать его из объекта obj2
obj2={}; obj2.say = obj1.say; obj2.say(); // выведет 'hello undefined'
Если мы хотим одолжить один метод и вызвать его в контексте другого - тогда всё хорошо. Но если нам не нужно изменять контекст выполнения функции? Тогда пример выше примет следующий вид.
obj2={}; obj2.speak = ()=>{obj1.say;}; obj2.speak(); // выведет 'hello boris'
Этот метод тоже можно использовать. Он работает пока работаем с объектами(в JavaScript функции тоже объекты) Но этот приём не сработает если мы захоти с эмитировать взятие адреса у свойства имющий значение примитивного типа(строка или числа). Это можно с эмитировать при помощи свойств аксесоров(get и set свойства).
Как видитие, имитировать указатели и ссылки в Javascript можно. Но использую только встроенные возможности языка - это громоздко, и потребно учитывать на какие типы данных потребно ссылка
Реализация ссылок при помощи AbstacktStock
Для на гляднасти я прпроведу ниже полный код реализации ссылок как на нативном JavaScript, так и использованием пакета AbstractStock.
Нативный JavaScript
с использованием AbstractStock
Как можно видеть из примеров выше - при использование AbstractStock, потребно определить блок инициализации, но определение самих ссыллок - проще и нагляднее. На демонстрационном примере разница не велика, но с ростом числа ссылок - код определения ссыллок уменьшается до половины. И становится гораздо наглядней.
Всех кого заинтересовал данный подход - прошу проследовать дальше.
Терминология
Для реализация задумки был введён ряд понятий:
Абстрактный накопитель - экземпляр AbstractStock. До вызова функции initStock абстрактный накопитель является не инициализированным и содержит лишь базовые методы. После вызова initStock становится возможно создовать абстрактные свойства при помощи метода abstractProp
Накопитель - внешний объект асоциированный с абстрактным накопителем. Ссылка на который хранится во внутренний переменной AS_stock. Все абстрактные свойства разрешаются в контексте накопителя. У абстрактного накопителя может быть только один накопитель который можно получит через свойство создоваемое в результате вызова функции initStock. Если в это свойство происходит запись значения - то происходит повторная привязка внешнего объекта, при этом свойство созданое при вызове функции initStock сохраняется прежним. Приэтом также изменяется контекст резрешения абстрактных свойств. Если же в новом контексте какое либо абстрактное свойство невозможно разрешить - то генерируется ошибка которая дополнена следующими свойствами:
- oldStock - прежний накопитель
- newStock - новый накопитель
- stockValidRes - объект валидации абстрактных свойств (см. функцию validStock)
Внешний объект - любой объект не осоцеированный с абстрактным накопителем
Абстрактное свойство - метод или свойство абстрактного накопителя созданное при помощи метода abstractProp. Абстрактное-свойство связано со свойством или методом накопителя. Эта связь определена во внутренней переменной ASlist. Обращатся с абстрактным-свойством возможно двумя способами:
- как с методом - если связано с методом(т.е вункцией)
- как с свойством - если связано со свойством(имеет объектный или примитивный тип данных)
Свойство объекта - свойство или метод любого объекта
Термины не упомянутые в списке выше расматриваются в обще принятом смысле
Внутренние переменные
Здесь описаны перменные на которых держится работа класса. Прямого досту к ним нет, но можно получить ккопию их значений или ссылку на них. Этот раздел введён в описани, так как приего наличии легче объяснить работу некоторых функций и некоторые термины
AS_stock
Хранит ссылку на внешний объект. Является частью накопителя который инициализируется функцией initStock. Именно в контексте этой переменной и разрешаются все Абстрактные-свойства.
ASlist
Внутренняя перменная экземпляра объекта AbstractStock. Является картой сопастовление абстрактных свойств. Перменная имеет тип объкта, значение свойств которой задаются внутри функции abstractProp.
Сама переменная имеет следуюй вид
где:
- abstractProp(string) - имя абстрактного свойства(параметр abstractname)
- stockProp(string) - имя свойства у внешнего объекта(параметр stockname)
Другими словами переменная является объектом, свойствами которого являются имена абстрактных свойств, а значениями имена свойств или методов накопителя
API
initStock(pname, pstock, [verrifF], [debug])
Инициализирует Накопитель и свойство(имя свойства указывается в параметре pname) у абстрактного накопителя через которое накопитель можно получить или же сделать накопителем другой внешний объект. Контроль над этими процессами можно расширить через callback функцию определяемую в параметре verrifF. Подробности смотри ниже.
парметры
name | type | Description | |||
---|---|---|---|---|---|
pname | String | имя накопителя (а также имя сойства, через которе будет даступен накопитель) | |||
pstock | Object | накопитель | |||
verrifF | undefined | NaN | null | Function | опциональный параметр определяющий callback функцию. Значение по умолчанию undefined. Позволяет расширять контроль присвоения и возврата накопителя при опращение к нему через свойство опрделенным в параметре pname. Подробности смотри ниже. |
debug | Boolean | Опциональный параметр. Значение по умолчанию false. Если устанавливается значение в true - то будет выводится дополнительная отладочная информация. Подробности смотри ниже. |
К одному экземпляру AbstractStock может быть привязан только один внешний объект, а повторный вызов метода initStock преведёт к следующим действиям:
- переопределяет накопитель (параметр pname)
- для доступа к накопителю создаёт новоё свойство у экземпляра класса AbstractStock
- изменит контекст выполнение всех абстрактных свойств определённых ранее.
- Привязка свойства для доступа к накопителю, определённое ранее, также будет изменена(будет возврощать объект указанный в параметре pstock)
Пример кода смотри ниже
подробное описание оциональных параметров: Функция сосздаёт свойство-аксессор т.е сосоздаёт get и set функции, которые при чтение и записи свойства и выполняют всю логику работы. callback функция, передаваемая в параметре virrifF, позволяет расширить их поведение путём её вызова, и получения значение, как перед возвратом, так и перед записью значения. В процесс вызова, в качестве параметра, передаётся объект дескриптор - который полностю описывает детали вызова. Полный список свойств дескриптора смотри выше
- verriF(desc) - её определение дополняет поведение свойства следующим образом:
- при чтение - вызывается перед возвратом значения, и возвращённый результат используется как результат чтения свойства. При вызове передаётся объект desc со следующими свойствами:
- name - (String) имя свойства. Т.е имя свойства абстрактного накопителя через которое осуществляется доступ к накопителю.
- val - (any) значение свойства. То самое значение которое должно возврощатся если функция verrifF не определена.
- context - (Object) контекст абстрактного свойства. т.е сам абстрактный накопитель
- stock - (Boolean) true
- get - (Boolean) true
- при записи - вызывается перед записью значения, и возвращённый результат используется как значение саписи свойства. При вызове передаётся объект desc со следующими свойствами: - name - (String) имя свойства. Т.е имя свойства абстрактного накопителя через которое осуществляется доступ к накопителю. - val - (any) значение свойства. То самое значение которое должно быть сохранено если verrifF не определена. - context - (Object) контекст абстрактного свойства. т.е сам абстрактный накопитель - stock - (Boolean) true - set - (Boolean) trueЕсли вкачестве значения параметра verrifF передано примитивное значение или объект отличный от объекта функции - то будет сгенерирована ошибка со следуещем содержанием 'TypeError: verrifF is not function'
- при чтение - вызывается перед возвратом значения, и возвращённый результат используется как результат чтения свойства. При вызове передаётся объект desc со следующими свойствами:
debug - (Boolean) по умолчанию значение false. Если передать значения true - то будет выведена дополнительная отладочная информация содержание которой зависит от значения параметра verrifF :
если параметр verrifF имеет неопределённое значение(undefined, null, NaN:) - то при определение абстрактного накопителя будет выведен блок сообщениё между строками '---start debug massage---' и '---end debug massage---\n'. Так же в режиме console.info будет выведена следующая информация:
- имя конструктора абстрактного накопителя
- имя накопителя (параметр pname)
- содержимое накопителя (параметр pstock)
- содержимо контекста определения накопителя(содержимо объекта this)
- cтэк вызова(вызывается функция console.trace() )
если значением параметра verrifF имеет значение примитивного типа или объект отличный от объекта Function - то при определение абстрактного накопителя перед генерацией ошибки через console.error() будет выведена следующая информация:
- имя конструктора абстрактного накопителя
- имя накопителя (параметр pname)
- содержимое накопителя (параметр pstock)
- значение параметра verrifF
содержимо контекста определения накопителя(содержимо объекта this)
abstractProp(abstractname, stockname, [verrifF], [debug])
Определяет или переопределяет уже существующее абстрактное свойство. Контроль над этими процессами можно расширить через callback функцию определяемую в параметре verrifF. Подробности смотри ниже.
парметры
name | type | Description | |||
---|---|---|---|---|---|
abstractname | String | имя абстрактного свойства | |||
stockname | string | имя свойства в накопителе | |||
verrifF | undefined | NaN | null | Function | опциональный параметр определяющий callback функцию. Значение по умолчанию undefined. Позволяет расширять контроль присвоения и возврата накопителя при опращение к нему через свойство опрделенным в параметре pname. Подробности смотри ниже. |
debug | Boolean | Опциональный параметр. Значение по умолчанию false. Если устанавливается значение в true - то будет выводится дополнительная отладочная информация. Подробности смотри ниже. |
Имя абстрактного свойства задоное в параметре abstractname становится доступным как свойство экземпляра класс AbstractStock
подробное описание оциональных параметров: Функция сосздаёт свойство-аксессор т.е сосоздаёт get и set функции, которые при чтение и записи свойства и выполняют всю логику работы. callback функция, передаваемая в параметре virrifF, позволяет расширить их поведение путём её вызова, и получения значение, как перед возвратом, так и перед записью значения. В процесс вызова, в качестве параметра, передаётся объект дескриптор - который полностю описывает детали вызова. Полный список свойств дескриптора смотри выше
verriF(desc) - её определение дополняет поведение свойства следующим образом:
- при чтение - вызывается перед возвратом значения, и возвращённый результат используется как результат чтения свойства. При вызове передаётся объект desc со следующими свойствами:
- name - (String) имя абстрактного свойства
- val - (any) значение абстрактного свойства. То самое значение которое должно возврощатся если функция verrifF не определена.
- context - (Object) контекст абстрактного свойства. т.е абстрактный накопитель
- prop - (Boolean) true
- get - (Boolean) true
- при записи - вызывается перед записью значения, и возвращённый результат используется как значение саписи свойства. При вызове передаётся объект desc со следующими свойствами: - name - (String) имя абстрактного свойства - val - (any) значение абстрактного свойства. То самое значение которое должно быть сохранено если verrifF не определена. - context - (Object) контекст абстрактного свойства. т.е абстрактный накопитель - prop - (Boolean) true - set - (Boolean) trueЕсли вкачестве значения параметра verrifF передано примитивное значение или объект отличный от объекта функции - то будет сгенерирована ошибка со следуещем содержанием 'TypeError: verrifF is not function'
- при чтение - вызывается перед возвратом значения, и возвращённый результат используется как результат чтения свойства. При вызове передаётся объект desc со следующими свойствами:
debug - (Boolean) по умолчанию значение false. Если передать значения true - то будет выведена дополнительная отладочная информация содержание которой зависит от значения параметра verrifF :
если параметр verrifF имеет неопределённое значение(undefined, null, NaN:) - то при определение абстрактного свойства будет выведен блок сообщениё между строками '---start debug massage---' и '---end debug massage---\n'. Так же в режиме console.info будет выведена следующая информация:
- имя конструктора абстрактного накопителя
- имя абстрактного свойства (параметр abstractname)
- имя свойства накопителе (параметр stockname)
- содержимо контекста определения накопителя(содержимо объекта this)
- cтэк вызова(вызывается функция console.trace() )
если значением параметра verrifF имеет значение примитивного типа или объект отличный от объекта Function - то при определение абстрактного свойства перед генерацией ошибки через console.error() будет выведена следующая информация:
- имя конструктора абстрактного накопителя
- имя абстрактного свойства (параметр abstractname)
- имя свойства накопителе (параметр stockname)
- значение параметра verrifF
содержимо контекста определения накопителя(содержимо объекта this)
пример
let arr = new Array(5,7,8)// это внешний объект(массив)
let as = new AbstractStock // экземпляр класса AbstractStock
//свяжем экземпляр класса AbstractStock с внешним объектом arr
let pname = "as_array"; // свойствоо с этим именем и будет накопителем
let pstock = arr; // ссылка на внешний объект.
as.initStock(pname, pstock);
//arr теперь доступен также под именем as.as_array , или as[pname]
console.log(arr === as[pname]);//true
console.log(arr === as.as_array);//true
// опрделелим as.in псевдонимом для метода arr.push
let abstractname = "in";
let stockname = "push";
as.abstractProp(abstractname, stockname);
//Обращаемся к определённому свойству
as[abstractname](11); // as.in(11) - будет тотже результат
console.log(arr);
//[ 5,7,8,11 ]
console.log(as[pname]); //или console.lof(as.as_array)
//[ 5,7,8,11 ]
// опрделелим as.count псевдонимом для свойства arr.length
let abstractname2 = "count";
let stockname2 = "length";
as.abstractProp(abstractname, stockname);
console.log(as.count) // или as[abstractname2]
//3
При переопределение абстрактного свойства в консоль выводится предупреждение в которое добавлены следующие свойства:
- oldval - пряжнее имя свойства в накопителе
- newVal - новое имя свойства в накопителе
- status - принимает значение true или false в зависимости от того, есть ли новое имя свойства в накопителе
- CALLSTACK - стэк вызова на моментнт определения абстрактного свойства
Если при определение нового абстрактное свойство,
в накопителе не найдено свойство с именем
указаным в пармететре stockname - в консоль будет выведено предупреждение, в которое
добавлены следующие свойства:
- stockname - имя свойства в накопителе
- status - иммет значение false
- CALLSTACK - стэк вызова на моментнт определения абстрактного свойства
getASlist
Метод возращает копию карты абстрактных свойств(копию значений переменной ASlist)
getStock
Возврощает ссылку на внутреннию переменную AS_stock, тем самым давая прямой доступ к накопителю. Данная возможность является экспериментальной. Её наличие и поведение могут быть изменены в следующих версиях.
AbstractStock.prototype.validStock
парметры
name | type | Description |
---|---|---|
pstock = this.getStock() optiona | String | Внешний объект для валидации с абстрактным накопителем. По умолчанию, в качестве Внешнего объекта используется накопитель. Т.е проверяет сам себя. |
Проверят возможность разрешения абстрактных свойств отнсительно внешнего объекта передоваемого через параметр pstock. В исходном коде(в коментариях указоно что эта функция проводит валидацию абстрактного накопителя. Это объясняется тем - что используется значение по умолчанию, и функция применяется для проверки коректности абстрактных свойст )
Возврощает объект с резултатами провкерки и имеет следующую структуру:
{
status,
abstractProps{
abstractProp{
stockProp,
statusProp
}
}
}
где:
status (boolean: true|false) - общий статус провекрки. true - всё хорошо, false - одно или более из Абстрактных свойств не прошло проверки.
abstractProps - предстовляет собой хеш таблицу, Ключами которой являются имена Абстрактных свойств(abstractProp), а значением каждого из клчей является объект содержащий следующие данные
- **stockProp** - имя свойства в объекте переданным через параметр *pstock* - **statusProp** (*boolean*: true|false) - статус проверки [Абстрактных свойствj](#Абстрактное-свойство)<br> *true* - имя свойства, переданного через **stockProp** есть в параметре *pstock* *false* - свойство, переданное через **stockProp** в параметре *pstock* не найдено.
deleteAbstractProp
Удаляет абстрактное свойство
парметры
name | type | Description |
---|---|---|
abstractname | String | Имя абстрактного свойства |
Returns: Boolean
Если абстрактное свойство с именем указаным в параметре abstractname найдено и его успешно удалось удалить - то функцией будет возвращено значение true. Так же будет удалена ссответсвующая запись из внутренней переменной ASlist
Если абстрактное свойство с именем указаным в параметре abstractname не найдено - то функцией будет возвращено значение false. Также в собщениях console.warn() будет выведена следующая информация:
- Имя конструктора абстрактного накопителя
- имя абстрактного свойства указанного в параметре abstractname
- все свойства абстрактного накопителя
- Содержимое карты абстрактных свойств (содержимое переменной ASlist)
- cтэк вызова(вызывается функция console.trace() )
deleteStock
Удаляет накопитель
парметры
name | type | Description |
---|---|---|
pname | String | имя накопителя |
Returns: Boolean
Если накопитель с именем указаным в параметре abstractname найден - то функция вернёт значение true. Таже произойдут следующие действия:
- Из абстрактного накопителя удаляются все абстрактные свойств.
- Очищается переменная ASlist
- Очищается переменная AS_stock
- Из абстрактного накопителя удаляется свойство соответсвующие накопителю (подробности этого свойства смотри в функции initStock)
Если накопитель с именем указаным в параметре abstractname не найден - то функция вернёт значение false. Таже console.warn() будет выведена следующая информация:
- Имя конструктора абстрактного накопителя
- имя абстрактного накопителя указанного в параметре pname
- все свойства абстрактного накопителя
- cтэк вызова(вызывается функция console.trace() )