Javascriptのクラスとメタクラス

JavaScriptの単一継承に使用するソリューションについてお話します。 非常に小さいため、他の場所で見つかる可能性があります。 読者の何人かがそれを役に立つと思うことを願っています。

これは、 Akshellプラットフォーム用に作成したフレームワークの一部です。ここに完全なソリューションコードドキュメントがあります 。 ただし、サーバー側のJavaScript環境では役立ちますが、サーバー側では、クラス階層の便利な作成が特に重要です。 __proto__プロパティ__proto__使用して作業をnew演算子で置き換える場合にも、クライアントで使用できます。

実際、ソリューション全体はFunctionクラスのsubclassメソッドにあります。 環境で許可されている場合は、列挙不可にする必要があります。

Function.prototype.subclass = function ( /* [constructor] [, prototype] */ ) {
var self = this ;
var constructor = (
typeof (arguments[0]) == 'function'
? Array.prototype.shift.call(arguments)
: ( this === Object
? function () {}
: function () { self.apply( this , arguments); }));
if (arguments[0])
constructor.prototype = arguments[0];
constructor.prototype.__proto__ = this .prototype;
constructor.__proto__ = this .__proto__;
return constructor;
};

この関数は、コンストラクターと作成されるクラスのプロトタイプという2つのオプション引数を取ります。 引数を渡すセマンティクスは非標準ですが、この場合は便利です。最初の引数が関数の場合はコンストラクター、それ以外の場合はプロトタイプです。

クラス階層のおもちゃの例:

var Figure = Object.subclass(
{
getArea: function () {
throw Error( 'Abstract' );
}
});

var Rectangle = Figure.subclass(
function (a, b) {
this .a = a;
this .b = b;
},
{
getArea: function () {
return this .a * this .b;
}
});

var Square = Rectangle.subclass(
function (a) {
Rectangle.call( this , a, a);
});

なぜなら コンストラクタはFunctionクラスのオブジェクトであるため、当然、 Functionサブクラスはクラスクラスまたはメタクラスです。 それらを定義することにより、クラスのインスタンス化を制御し、サブクラスに継承されたクラスの静的プロパティとメソッドを決定できます(サブクラスは、 subclassメソッドの最後から2番目の行で親からメタクラスを受け取ります)。

たとえば、 Figureサブクラスを演算子なしでインスタンス化し、各サブクラスにoptionalNewプロパティがtrue設定されるようにしtrue 。 これを行うには、Figureのメタクラスを記述します。

var FigureMeta = Function.subclass(
{
subclass: function () {
var constructor = Function.prototype.subclass.apply( this , arguments);
var result = function () {
var self = (
this instanceof arguments.callee
? this
: {__proto__: arguments.callee.prototype});
constructor.apply(self, arguments);
return self;
};
result.prototype = constructor.prototype;
result.__proto__ = this .__proto__;
return result;
},

optionalNew: true
});

Figure.__proto__ = FigureMeta.prototype;


メタクラスのインストール後に定義されたFigureすべてのサブクラスは、必要な変更を受け取ります。

もちろん、メタクラスはあまり広く使用すべきではありません。特に、 FigureMetaは完全にFigureMetaな例です。 ただし、場合によっては、コードをはるかに短く理解しやすくすることができます。 たとえば、JavaScriptのDjangoフォームポートであるAkshellのjs-formsライブラリを適応させる場合、メタクラスを使用すると、Djangoと同じ宣言的な方法でフォームのサブクラスを作成できます(これにもPythonのみが使用されます)。 コードはわずか30行です。

Source: https://habr.com/ru/post/J94070/


All Articles