JavaScript を使っていて継承 extends した場合に static の挙動がどうなるのか気になったので調べてみた。

  1. 継承した class 名で親の static 要素は利用できるのか
  2. オーバーライドが可能か?

1. 継承した class 名で親の static 要素は利用できるのか

まずは継承したら元の static は利用できるのかどうかを検証する。

検証

以下のサイトのコードを引用して、それを継承した Hoge クラスを作り、各 static な要素を検証してきます。

static - JavaScript | MDN

The static keyword defines a static method or field for a class, or a static initialization block (see the link for more information about this usage). Static properties cannot be directly accessed on instances of the class. Instead, they're accessed on the class itself.

class ClassWithStaticMethod {
  static staticProperty = 'someValue';
  static staticMethod() {
    return 'static method has been called.';
  }
  static {
    console.log('Class static initialization block called');
  }
}

console.log(ClassWithStaticMethod.staticProperty);
// Expected output: "someValue"
console.log(ClassWithStaticMethod.staticMethod());
// Expected output: "static method has been called."

class Hoge extends ClassWithStaticMethod {
}

console.log(Hoge.staticProperty);
console.log(Hoge.staticMethod());

出力結果

> "Class static initialization block called"
> "someValue"
> "static method has been called."
> "someValue"
> "static method has been called."

問題なく呼ぶことができました。

2. オーバーライドが可能か?

次に static はオーバーライドできるかどうかです。 JavaScript は自由度がいい意味でも悪い意味でも高いので、おそらくできてしまうだろうというのが予想です。

さて、実際にはどうなのか検証していきます。

1と同様に以下のサイトのコードを引用して、それを継承した Hoge クラスを作り、各 static をオーバーライドしていきます。

static - JavaScript | MDN

The static keyword defines a static method or field for a class, or a static initialization block (see the link for more information about this usage). Static properties cannot be directly accessed on instances of the class. Instead, they're accessed on the class itself.

検証

オーバーライドできた場合は メタ構文変数 が表示されます。

class ClassWithStaticMethod {
  static staticProperty = 'someValue';
  static staticMethod() {
    return 'static method has been called.';
  }
  static {
    console.log('Class static initialization block called');
  }
}

console.log(ClassWithStaticMethod.staticProperty);
// Expected output: "someValue"
console.log(ClassWithStaticMethod.staticMethod());
// Expected output: "static method has been called."

class Hoge extends ClassWithStaticMethod {
  static staticProperty = 'fuga';
  static staticMethod() {
    return "piyo";
  }
  static {
    console.log("hogera");
  }
}

console.log(Hoge.staticProperty);
console.log(Hoge.staticMethod());

出力結果

> "Class static initialization block called"
> "someValue"
> "static method has been called."
> "hogera"
> "fuga"
> "piyo"

継承は可能ということがわかった。

static な initializer は 1 度しか呼ばれない。 ただし、継承後の initializer は親の initializer が呼ばれた後でも 1 度だけ呼ばれる。

結論

JavaScript を使っていて継承 extends した場合

  • 継承後のクラス名でも static 要素を利用することができた。
  • オーバーライドが可能。
  • initializer は別途1度だけ呼ばれる。

となった。