1. ホーム
  2. javascript

[解決済み] タイプスクリプト。2つのクラスを拡張するには?

2022-10-20 21:02:29

質問

PIXIクラス(2D WebGlレンダラライブラリ)を拡張するクラス間で、時間を節約して共通のコードを再利用したいのです。

オブジェクトインターフェイスです。

module Game.Core {
    export interface IObject {}

    export interface IManagedObject extends IObject{
        getKeyInManager(key: string): string;
        setKeyInManager(key: string): IObject;
    }
}

私の問題は getKeyInManagersetKeyInManager は変更しないので、重複しないように再利用したいのですが、その実装を紹介します。

export class ObjectThatShouldAlsoBeExtended{
    private _keyInManager: string;

    public getKeyInManager(key: string): string{
        return this._keyInManager;
    }

    public setKeyInManager(key: string): DisplayObject{
        this._keyInManager = key;
        return this;
    }
}

私がやりたいことは、自動的に Manager.add() を通して、オブジェクトを参照するためにマネージャで使用されるキー 内部 プロパティにあるオブジェクト自身 _keyInManager .

では、Textureを使った例を見てみましょう。ここでは TextureManager

module Game.Managers {
    export class TextureManager extends Game.Managers.Manager {

        public createFromLocalImage(name: string, relativePath: string): Game.Core.Texture{
            return this.add(name, Game.Core.Texture.fromImage("/" + relativePath)).get(name);
        }
    }
}

をすると this.add() を実行するとき、私は Game.Managers.Manager add() メソッドによって返されたオブジェクトに存在するメソッドを呼び出したい。 Game.Core.Texture.fromImage("/" + relativePath) . このオブジェクトは、この例では Texture :

module Game.Core {
    // I must extend PIXI.Texture, but I need to inject the methods in IManagedObject.
    export class Texture extends PIXI.Texture {

    }
}

私が知っているのは IManagedObject はインターフェースであり、実装を含むことができないことは知っていますが、クラス ObjectThatShouldAlsoBeExtended の中に Texture クラスの中にあります。同じプロセスが Sprite , TilingSprite , Layer などがあります。

私はここで経験豊富なTypeScriptのフィードバック/アドバイスが必要です、それはそれを行うことが可能でなければなりませんが、その時点で1つしか可能でないので、複数の拡張によってではなく、私は他の解決策を見つけられませんでした。

どのように解決するのですか?

TypeScriptにはあまり知られていない機能として、Mixinを使用して再利用可能な小さなオブジェクトを作成することができるものがあります。多重継承を使用して、これらをより大きなオブジェクトにまとめることができます (多重継承はクラスでは許可されませんが、ミキシンは許可されます。)

TypeScript Mixinの詳細

このテクニックを使って、ゲーム内の多くのクラス間で共通のコンポーネントを共有したり、ゲーム内の1つのクラスから多くのコンポーネントを再利用したりすることができると思います。

Mixinsの簡単なデモです...まず、混ぜたいフレーバーです。

class CanEat {
    public eat() {
        alert('Munch Munch.');
    }
}

class CanSleep {
    sleep() {
        alert('Zzzzzzz.');
    }
}

次に、Mixinを作成するためのマジックメソッド(これはプログラムのどこかで一度だけ必要です...)です。

function applyMixins(derivedCtor: any, baseCtors: any[]) {
    baseCtors.forEach(baseCtor => {
        Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
             if (name !== 'constructor') {
                derivedCtor.prototype[name] = baseCtor.prototype[name];
            }
        });
    }); 
}

そして、mixinフレーバーから多重継承されたクラスを作成することができます。

class Being implements CanEat, CanSleep {
        eat: () => void;
        sleep: () => void;
}
applyMixins (Being, [CanEat, CanSleep]);

このクラスには実際の実装がないことに注意してください。しかし、このクラスを使用すると、すべてが動作します。

var being = new Being();

// Zzzzzzz...
being.sleep();