2.2TypeScript公式Handbook「Classes」をもとにした解説です。6)には構文にクラスが加わりました。TypeScriptも、この仕様に沿ってクラスを採り入れています。コンパイルされるJavaScriptコードは、ES6に対応する前のブラウザで動きます。クラスを定めるクラスはclassキーワードで定めます。つぎのクラス(Point)は、コンストラクタ(constructor())に渡したふたつの引数(xy座標)をプロパティに与えてインスタンスがつくられます。クラスの中でメンバー(プロパティとメソッド)を参照するには、thisを添えなければなりません。メソッド(getCoords())を呼び出せば、それらの値をプロパティとしてもつオブジェクトが得られます。関数(function)と異なり、定義する前に参照したり、コンストラクタを呼び出そうとするとエラー(ReferenceError)になります。継承するextendsキーワードを以下のように用いて、クラスは継承できます。クラスを継承して使う」参照)。サブクラスのコンストラクタは、本体から関数super()でスーパークラスのコンストラクタを呼び出します。この呼び出しをする前に、this参照はできません。ふたつのサブクラスにはともに、スーパークラスのxy座標のプロパティ(xとy)、および原点から座標までの距離を返すメソッド(getLength())が継承されます。ひとつめのサブクラスVectorは、コンストラクタが受け取ったxy座標の引数を、そのままsuper()関数でスーパークラスに渡しています。独自のメソッドgetAngle()は、Math.atan2()メソッドにより原点とxy座標のなす角度を返します。ひとつのサブクラスPolarでは、原点からの距離と角度を引数としてインスタンスがつくられます。コンストラクタはスーパークラスのコンストラクタに渡す引数(xとy)の値を求め、受け取った引数から独自のプロパティ(radiusとangle)も定めています(距離と角度から座標を求める計算については「sinとcosは何する関数?」をご参照ください)。原点と座標との角度を返す独自のメソッドgetAngle()が加えられたほか、親クラスのメソッドgetLength()を定義し直しました(オーバーライド)。プロパティ値(radius)をそのまま返せば済むからです。this.angle;}}ふたつのサブクラスをつぎのように試してみます。√3)ですので、原点からの距離は2です。ひとつめのサブクラス(Vector)のインスタンス(vector)は、スーパークラスから継承したメソッド(getLength())で距離を得ました。計算上の誤差がわずかに生じています。ふたつめのサブクラス(Polar)のインスタンス(polar)は、オーバーライドしたメソッド(getLength())により、コンストラクタが受け取ったプロパティ値(radius)をそのまま返しているため誤差がありません。アクセス修飾子を使うアクセス修飾子を使うと、SNSのようにクラスのメンバーの公開範囲が決められます(図001)。デフォルトはすべてに公開されるpublicです。privateのメンバーは、そのクラスの中でしか参照できません。そのクラスと継承したサブクラスだけ扱えるのがprotectedです。デフォルトはpublicクラスのメンバーにアクセス修飾子を添えないと、publicとみなされます。つぎのクラスでpublic修飾子を省いても、同じ定義だということです。メンバーはすべてクラスの外から参照できます。private修飾子でアクセス制限するprivate修飾子を添えたメンバーは、クラスの中からしか参照できません。サブクラスはスーパークラスのprivateなメンバーを継承します。サブクラスであっても、アクセスはできないのです。つぎのように親クラス(Point)に備えたprivateでないメソッド(getCoords())から値を得なければなりません。設定のメソッドがなければ、プロパティは読み取り専用になります。型の互換性」02「プロパティとその型で互換性を調べる」参照)。メンバーがすべてpublicの場合にかぎります。private(あるいは後述するprotected)のメンバーについては、属するクラスも同じでなければなりません。privateのメンバーをもつクラスで型づけすると、そのクラスかサブクラスのインスタンスしか合わないのです。つぎのふたつのクラスPointとCoordsは、メンバーの名前と型づけ、およびprivate修飾子までまったく同じです。privateなメンバーの属するクラスが異なるので型は合いません。サブクラスVectorのインスタンスは親のprivateなメンバーを継承するため、型が合うとされるのです。protected修飾子のメンバーをサブクラスから参照するprotected修飾子を添えたメンバーは、定めたクラスとサブクラスのみ参照できます。つぎのクラスPointは、protectedのメソッド(getSquaredSum())がprivateの座標のプロパティ(xとy)から、原点との差の平方和を返すことにしました。3次元座標のサブクラス(Vector3D)はz座標が加わるので、原点からの距離はオーバーライドしたメソッド(getLength())で求めます。protectedのメソッドから得たxy座標の平方和にz座標の2乗を加えた平方根が距離です[*1]。√3)のインスタンス(vector3d)をつくりました。オーバーライドしたメソッド(getLength())は、スーパークラスのprotectedのメソッド(getSquaredSum())が返す値から、距離を求めています。protectedのメソッドを、外から直接インスタンスに対して呼び出せばエラーになります。protectedのメソッドは外から呼び出せないのでエラーprotected修飾子をコンストラクタ(constructor())に与えることもできます。そのクラスのインスタンスは、コンストラクタを外から呼び出してつくることができません。クラスの継承はできますので、サブクラスのコンストラクタから関数super()で呼び出すことになります。z)の原点からの距離は、各座標の平方和を開いて得られます(図002)。引数でプロパティを定めるコンストラクタが受け取った引数の値をそのままプロパティに与える場合には、引数でプロパティ宣言できます。そのためには、引数にアクセス修飾子(または後述のreadonly修飾子)を添えるだけです。プロパティ宣言のステートメントや代入の式が省けるので、コードは短くなります。静的なメンバーを定める静的なメンバーは、インスタンスをつくらずに、クラスから参照します。添える修飾子はstaticです。つぎのコードは、スーパークラス(Point)に静的プロパティ(radToDeg)、サブクラス(Vector)に静的メソッド(toDegree())を定めました。静的プロパティradToDegは、角度の単位ラジアンから度数への変換比率です。静的メソッドtoDegree()は、その比率を用いて、渡された引数のラジアン角を度数値に変換します。静的メソッドの本体からスーパークラスの静的メンバーを参照するには、クラスのほかにキーワードsuperも使えます。2.0のreadonly修飾子」参照)。つぎのように、静的なプロパティ(RAD_TO_DEG)を値の変えられないクラス定数にすることもできるのです。readonlyプロパティは、コンストラクタからであれば値が改められます。つぎのコードは、クラス(Item)のprivateな静的プロパティ(nextId)と組み合わせて、コンストラクタでreadonlyのプロパティ(id)に整数連番を与えます。get/setアクセサを使う」参照)。メソッド名の前にgetまたはsetのキーワードを添えれば、その名前をプロパティのようにして、値の取り出しや書き替えができるのです。つぎのコードでは、スーパークラス(Point)が座標のprivateなプロパティ(xとy)をもち、メソッドでそれらの座標の取得・設定(getCoords()とsetCoords())や原点からの距離(getLength())も得られるのです。get/setアクセサはサブクラス(Vector)に定め、座標が原点となすラジアン角をプロパティ(angle)のかたちで、取得・設定できるようにしました。プロパティそのものはありませんので、アクセサが参照されるたびに値は計算されます。}readonly修飾子で定めたプロパティを、getアクセサで書き替えることもできます。setアクセサが加えられていなければ、読み取り専用になるからです。Math.PI;}readonly修飾子でもgetアクセサでも、同じように定数が定められます。コンパイルされるJavaScriptコードの実装は違います。readonly修飾子の場合、JavaScriptには読み取り専用の修飾子がないので、プロパティはただクラスに加えられるだけです。そのため、実行時に値が書き替えられます(図003)。5.1からget構文が備わりました。getアクセサはこの構文にコンパイルされるため、返す値は実行時も書き替えできません(図004)。5より前の設定では使えないことにご注意ください。2015とではつぎのように異なります。抽象クラスを継承する抽象クラスは、サブクラスで継承する基本クラス(スーパークラス)です。クラスの前にabstract修飾子を添えます。抽象クラスのメンバーにabstract修飾子を与えれば、インタフェース(interface)と同じように、サブクラスは同じ名前で同じ型づけのメンバーを備えなければなりません。abstract修飾子を添えたメンバーには、インタフェースと同じく、実装は書きません。クラスを納める型づけ変数にクラスを型として与えると、クラスのインスタンスが代入できます。以下のクラスPointが定められているとき、そのクラスで型づけした変数(point)にインスタンスを納めて、メソッドが呼び出せます。angle;}}では、クラスそのものを変数に入れたいとき、どのように型を決めたらよいでしょう。その場合、キーワードtypeofにクラスを添えて型づけします(「TypeScript早わかりチートシート【1.5.3対応】」の「型クエリ」参照)。すると、変数にクラス(コンストラクタ関数)がそっくり納められます。その変数をクラスの参照としてインスタンスがつくれますし、静的なプロパティの値もつぎのように書き替えられます。クラスでインタフェースを拡張するクラスはインタフェースが継承することもできます。継承するのはメンバーの名前と型づけだけで、実装は含まれません。インタフェース(IVector3D)を実装(implements)したサブクラス(Vector3D)は、改めて継承されたクラス(Point)のメンバーを実装しなければならないのです。インタフェース」10「クラスでインタフェースを拡張する」をご参照ください。2インタフェースが継承したクラスを、別にスーパークラスとして拡張することもできます。その場合には、親クラスの実装が継承されます。