Примечание: в данном способе возможно содержится небольшая ошибка.
<!DOCTYPE html>
<html>
<head>
<script>
var ParentClass = new Class (function () {
// constructor
function ParentClass (initVar) {
this.initVar = initVar;
this._x = 0; // getter | setter
document.addEventListener('click', this._privateMethod, false);
console.log('ParentClass constructed.');
}
// destructor
ParentClass.prototype.destroy = function () {
document.removeEventListener('click', this._privateMethod, false);
console.log('ParentClass destroyed.');
};
// default
ParentClass.prototype.defaultVar = 'ParentClass default var.';
// public
ParentClass.prototype.publicMethod = function () {return 'ParentClass public method.';};
// private - interface check
ParentClass.prototype._privateMethod = function () {console.log('ParentClass private method.');};
// abstract - interface check
ParentClass.prototype.abstractMethod = function () {};
// final - interface check
ParentClass.prototype.finalMethod = function () {return 'ParentClass final method.';};
// static
ParentClass.staticMethod = function () {return 'ParentClass static method.';};
// getter | setter
Object.defineProperty(ParentClass.prototype, 'x', {
get: function () {return this._x;}
, set: function (value) {this._x = value;}
, enumerable: true
, configurable: true
});
return ParentClass;
});
var MixinClass = new Class (function () {
// constructor
function MixinClass () {}
// public
MixinClass.prototype.mixinPublicMethod = function () {return 'MixinClass public method.';};
// static
MixinClass.mixinStaticMethod = function () {return 'MixinClass static method.';};
return MixinClass;
});
var ChildClass = new Class ({extends: ParentClass, mixin: MixinClass}, function (_super) {
// singleton
var singleton;
// constructor
function ChildClass (initVar) {
if (singleton) {return singleton} else {singleton = this;}
_super.call(this, initVar);
}
// public - parent call
ChildClass.prototype.childPublicMethod = function () {
return 'ChildClass childPublicMethod call ' + _super.prototype.publicMethod.call(this);
};
// override
ChildClass.prototype.abstractMethod = function () {return 'ChildClass override ParentClass abstarctMethod.';};
// override private
ChildClass.prototype._privateMethod = function () {console.log('ChildClass private method.');};
return ChildClass;
});
function _mixin (ChildClass) {
var mixinClasses = Array.prototype.slice.call(arguments, 1)
, key
, len
, i;
if (mixinClasses.length > 0) {
if (Object.prototype.toString.call(mixinClasses[0]) === '[object Array]') {mixinClasses = mixinClasses[0];}
for (i = 0, len = mixinClasses.length; i < len; i++) {
for (key in mixinClasses[i]) {if (mixinClasses[i].hasOwnProperty(key)) {ChildClass[key] = mixinClasses[i][key];}}
for (key in mixinClasses[i].prototype) {if (key !== 'constructor') {ChildClass.prototype[key] = mixinClasses[i].prototype[key];}}
}
}
}
function Class () {
var Constructor
, len
, key
, i
, tempObject;
function F () {}
if (
arguments.length === 1
&& Object.prototype.toString.call(arguments[0]) === '[object Function]'
) {
return arguments[0]();
} else if (
arguments.length === 2
&& Object.prototype.toString.call(arguments[0]) === '[object Object]'
&& Object.prototype.toString.call(arguments[1]) === '[object Function]'
) {
if (arguments[0].hasOwnProperty('extends')) {
Constructor = arguments[1](arguments[0]['extends']);
for (key in arguments[0]['extends']) {
if (!Constructor.hasOwnProperty(key)) {Constructor[key] = arguments[0]['extends'][key];}
}
F.prototype = arguments[0]['extends'].prototype;
tempObject = new F();
for (key in tempObject) {
if (!Constructor.prototype.hasOwnProperty(key)) {Constructor.prototype[key] = tempObject[key];}
}
} else {
Constructor = arguments[1]();
}
if (arguments[0].hasOwnProperty('mixin')) {_mixin(Constructor, arguments[0]['mixin']);}
return Constructor;
} else {
throw new Error('Argument of new Class constructor must be object or function');
}
}
console.log('ParentClass static');
console.dir(ParentClass);
console.log('ParentClass public');
console.dir(ParentClass.prototype);
var parentObject = new ParentClass('ParentClass init var');
console.log('1) Constructor name: ' + parentObject.constructor.name);
console.log('2) DeafultVar value: ' + parentObject.defaultVar);
console.log('3) InitVar value: ' + parentObject.initVar);
console.log('4) PublicMethod result: ' + parentObject.publicMethod());
console.log('5) AbstractMethod result: ' + parentObject.abstractMethod());
console.log('6) FinalMethod result: ' + parentObject.finalMethod());
console.log('7) StaticMethod result: ' + ParentClass.staticMethod());
console.log('8) Get x result: ' + parentObject.x);
console.log('9) Set x.');
parentObject.x = 1;
console.log('10) Get x after set: ' + parentObject.x);
setTimeout(function(){console.log('11) Object destruction. '); parentObject.destroy(); parentObject = null;}, 5000);
console.log('MixinClass static');
console.dir(MixinClass);
console.log('MixinClass public');
console.dir(MixinClass.prototype);
console.log('ChildClass static');
console.dir(ChildClass);
console.log('ChildClass public');
console.dir(ChildClass.prototype);
var childObject = new ChildClass('ChildClass init var 1');
console.log('1) ChildClass object 1 created.');
var childObject2 = new ChildClass('ChildClass init var 2');
console.log('2) ChildClass object 2 created.');
console.log('3) Is singleton? ' + (childObject === childObject2));
console.log('4) Constructor name: ' + childObject.constructor.name);
console.log('5) DeafultVar value: ' + childObject.defaultVar);
console.log('6) InitVar value: ' + childObject.initVar);
console.log('7) PublicMethod result: ' + childObject.publicMethod());
console.log('8) ChildPublicMethod result: ' + childObject.childPublicMethod());
console.log('9) AbstractMethod result: ' + childObject.abstractMethod());
console.log('10) FinalMethod result: ' + childObject.finalMethod());
console.log('11) StaticMethod result: ' + ChildClass.staticMethod());
console.log('12) Get x result: ' + childObject.x);
console.log('13) Set x.');
childObject.x = 2;
console.log('14) Get x after set: ' + childObject.x);
console.log('15) MixinPublicMethod result: ' + childObject.mixinPublicMethod());
console.log('16) MixinStaticMethod result: ' + ChildClass.mixinStaticMethod());
setTimeout(function(){console.log('17) Object destruction. '); childObject.destroy(); childObject = null;}, 5000);
</script>
</head>
<body>
</body>
</html>
Комментариев нет:
Отправить комментарий