

JavaScriptでClassAで使用した変数をClassBでも使用するにはどのようにコードを書いたら良いでしょうか？

[code]

    class A {
        constructor {
            this.A
        }
    
    }
    
    class B {
        constructor {
            this.B
        }
    
        method {
            //こういった感じでclassBでclassAのコンストラクタ変数を使用したい。
            console.log(this.A);
        }
    }
    
[/code]

## classAとclassBの関係性

フラグ機能を作りたくて、classAで初期化された値があって、それをclassBでの処理・実行と共に変更を加えたいと思ってます。ClassBにflagを作成すると処理と共に初期化されてしまいます。それを回避出来たらいいんですが、現状思い付けないのでこの方法を取ろうと考えています。


CC BY-SA 4.0
2020-12-25T11:16:07.140
72886
2020-12-29T08:41:31.867
2020-12-29T08:41:31.867
22565
22565
question
javascript
classAのコンストラクタで作成した変数をClassBに継承して使用したい。


クラスの継承を使うと実現できます。

[code]

    class A {
        constructor {
            this.A
        }
    
    }
    
    class B extends A {
        constructor {
            super() // <-- A の constructor() を呼び出す
            this.B
        }
    
        method {
            console.log(this.A);
        }
    }
    
[/code]

ただし継承自体混乱の元になるのであまりおすすめはできません。特に何回も継承を繰り返すと変数がどこに行ったかわからなくなりますし。クラス自体なるべく使わないでできないか考えて設計するときれいにできるでしょう。

### 継承の問題点について

名前こそ prototype-chain
ですがやっていることは動的型付け言語における継承とほぼ同じです。「変数がどこに行ったかわからなくなります」と述べたとおり名前空間の混乱を引き起こします。これは初学者や大きなプロジェクトへの新規参入者にとって厄介な問題です。

また、回答では述べませんでしたが「継承を繰り返すとクラスが大きくなることはあっても小さくなることはない」という問題もつきまといます。プロパティがどんどん増えオブジェクトの利用者には分かりづらいものとなるでしょう。例えば
A を継承した B を引数に取る関数も、A
が誤って渡された場合に備えプロパティのチェックを行わなければいけません。動的型付け言語ではプロパティのチェックもプログラマの責任です。チェックを怠れば安全なプログラムではなくなるのです。

そしてこれは「差分プログラミング」という問題を引き起こします。差分プログラムとは「クラスを継承して追加機能だけを実装すればよい」という考え方です。一見理想的なやり方のように見えますが。これをやられると継承先の実装を見ただけでは最終的なオブジェクトの持つプロパティの全貌が読めないというものです。`class`
ならまだよいものの prototype-chain を多用して書かれたソースコードは非常に追いにくいものになります。

「公式がやっているからやってもよい」ではないのです。継承とは本来注意深く設計した上で行わないと様々な問題を引き起こす厄介な概念なのです。また、継承という方法は「その時代はそれしか方法が広く知られてなかっただけでそうするしかなかった」のです。なぜ
TypeScript やその他 AltJS が出て JavaScript にコンパイルするようになったかを、また、2010
年代に話題になっているプログラミング言語にオブジェクトの継承に相当する機能がない、もしくはオブジェクトという概念自体がないのかを考える必要があります。

JavaScript
や動的型付け言語におけるクラス、オブジェクトの継承はできることを増やしてくれる魔法のようです。それらを好む理由もわからなくはありません。しかしわたしは最後にこの言葉を引用してまとめとしたいと思います。

> 「これ以上付け加える物が無くなった時でなく、これ以上取り去る物が無くなった時が完成だ」 ― アントワーヌ・ド・サン＝テグジュペリ


CC BY-SA 4.0
2020-12-25T14:43:48.343
72890
2020-12-28T16:18:16.557
2020-12-28T16:18:16.557
39645
39645
72886
answer


継承先はextendsを記載し、かつコンストラクタでsuper()を呼び出します。

[code]

    class Mover {
        constructor(x, y, imgFileName, imgOffsetX, imgOffsetY) {
            this.x = x;
            this.y = y;
            this.img = new Image();
            this.img.src = imgFileName;
            this.imgOffsetX = imgOffsetX;
            this.imgOffsetY = imgOffsetY;
            this.collisions = [];
            this.moveX = 0;
            this.moveY = 0;
        }
        ...
    }
    
    class Player extends Mover {
        constructor(x, y, imgFileName, imgOffsetX, imgOffsetY) {
            super(x, y, imgFileName, imgOffsetX, imgOffsetY);
            this.collisions.push(new Collision(-10, 0, 16));
            this.collisions.push(new Collision(+16, 0, 16));
            this.isJumping = false;
        }
        ...
    }
    
[/code]

速度に問題がない場合、テストしやすいように以下のルールを徹底しておくと良いでしょう  
・クラスが使用する別のクラスは、自分でnewせずコンストラクタの引数で受け取る（DI）  
（上記では、Collisionクラスを勝手にnewしてしまっているので、厳密には悪い例です）  
・上記の量が増えてくるとコンストラクタでコンストラクタが…となってくるので、  
適当なタイミングでDIコンテナの導入を考えましょう


CC BY-SA 4.0
2020-12-26T03:57:35.390
72899
2020-12-26T03:57:35.390
25396
72886
answer